Home Article Practice quickjs

quickjs

2021-02-24 22:47  views:857  source:小键人995476    

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <limits.h>
#include <sys/stat.h>
#include <dirent.h>
#if defined(_WIN32)
#include <windows.h>
#include <conio.h>
#include <utime.h>
#else
#include <dlfcn.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#if defined(__APPLE__)
typedef sig_t sighandler_t;
#if !defined(environ)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#endif
#endif /* __APPLE__ */
#endif
#if !defined(_WIN32)
/* enable the os.Worker API. IT relies on POSIX threads */
#define USE_WORKER
#endif
#ifdef USE_WORKER
#include <pthread.h>
#include <stdatomic.h>
#endif
#include "cutils.h"
#include "list.h"
#include "quickjs-libc.h"
/* TODO:
- add socket calls
*/
typedef struct {
struct list_head link;
int fd;
JSValue rw_func[2];
} JSOSRWHandler;
typedef struct {
struct list_head link;
int sig_num;
JSValue func;
} JSOSSignalHandler;
typedef struct {
struct list_head link;
BOOL has_object;
int64_t timeout;
JSValue func;
} JSOSTimer;
typedef struct {
struct list_head link;
uint8_t *data;
size_t data_len;
/* list of SharedArrayBuffers, necessary to free the message */
uint8_t **sab_tab;
size_t sab_tab_len;
} JSWorkerMessage;
typedef struct {
int ref_count;
#ifdef USE_WORKER
pthread_mutex_t mutex;
#endif
struct list_head msg_queue; /* list of JSWorkerMessage.link */
int read_fd;
int write_fd;
} JSWorkerMessagePipe;
typedef struct {
struct list_head link;
JSWorkerMessagePipe *recv_pipe;
JSValue on_message_func;
} JSWorkerMessageHandler;
typedef struct JSThreadState {
struct list_head os_rw_handlers; /* list of JSOSRWHandler.link */
struct list_head os_signal_handlers; /* list JSOSSignalHandler.link */
struct list_head os_timers; /* list of JSOSTimer.link */
struct list_head port_list; /* list of JSWorkerMessageHandler.link */
int eval_script_recurse; /* only used in the main thread */
/* not used in the main thread */
JSWorkerMessagePipe *recv_pipe, *send_pipe;
} JSThreadState;
static uint64_t os_pending_signals;
static int (*os_poll_func)(JSContext *ctx);
static void js_std_dbuf_init(JSContext *ctx, DynBuf *s)
{
dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc *)js_realloc_rt);
}
static BOOL my_isdigit(int c)
{
return (c >= '0' && c <= '9');
}
static JSValue js_printf_internal(JSContext *ctx,
int argc, JSValueConst *argv, FILE *fp)
{
char fmtbuf[32];
uint8_t cbuf[UTF8_CHAR_LEN_MAX+1];
JSValue res;
DynBuf dbuf;
const char *fmt_str;
const uint8_t *fmt, *fmt_end;
const uint8_t *p;
char *q;
int i, c, len, mod;
size_t fmt_len;
int32_t int32_arg;
int64_t int64_arg;
double double_arg;
const char *string_arg;
/* Use indirect call to dbuf_printf to prevent gcc warning */
int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = (void*)dbuf_printf;
js_std_dbuf_init(ctx, &dbuf);
if (argc > 0) {
fmt_str = JS_ToCStringLen(ctx, &fmt_len, argv[0]);
if (!fmt_str)
goto fail;
i = 1;
fmt = (const uint8_t *)fmt_str;
fmt_end = fmt + fmt_len;
while (fmt < fmt_end) {
for (p = fmt; fmt < fmt_end && *fmt != '%'; fmt++)
continue;
dbuf_put(&dbuf, p, fmt - p);
if (fmt >= fmt_end)
break;
q = fmtbuf;
*q++ = *fmt++; /* copy '%' */
/* flags */
for(;;) {
c = *fmt;
if (c == '0' || c == '#' || c == '+' || c == '-' || c == ' ' ||
c == '\'') {
if (q >= fmtbuf + sizeof(fmtbuf) - 1)
goto invalid;
*q++ = c;
fmt++;
} else {
break;
}
}
/* width */
if (*fmt == '*') {
if (i >= argc)
goto missing;
if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
goto fail;
q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg);
fmt++;
} else {
while (my_isdigit(*fmt)) {
if (q >= fmtbuf + sizeof(fmtbuf) - 1)
goto invalid;
*q++ = *fmt++;
}
}
if (*fmt == '.') {
if (q >= fmtbuf + sizeof(fmtbuf) - 1)
goto invalid;
*q++ = *fmt++;
if (*fmt == '*') {
if (i >= argc)
goto missing;
if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
goto fail;
q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg);
fmt++;
} else {
while (my_isdigit(*fmt)) {
if (q >= fmtbuf + sizeof(fmtbuf) - 1)
goto invalid;
*q++ = *fmt++;
}
}
}
/* we only support the "l" modifier for 64 bit numbers */
mod = ' ';
if (*fmt == 'l') {
mod = *fmt++;
}
/* type */
c = *fmt++;
if (q >= fmtbuf + sizeof(fmtbuf) - 1)
goto invalid;
*q++ = c;
*q = '\0';
switch (c) {
case 'c':
if (i >= argc)
goto missing;
if (JS_IsString(argv[i])) {
string_arg = JS_ToCString(ctx, argv[i++]);
if (!string_arg)
goto fail;
JS_FreeCString(ctx, string_arg);
} else {
if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
goto fail;
}
/* handle utf-8 encoding explicitly */
if ((unsigned)int32_arg > 0x10FFFF)
int32_arg = 0xFFFD;
/* ignore conversion flags, width and precision */
len = unicode_to_utf8(cbuf, int32_arg);
dbuf_put(&dbuf, cbuf, len);
break;
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
if (i >= argc)
goto missing;
if (JS_ToInt64Ext(ctx, &int64_arg, argv[i++]))
goto fail;
if (mod == 'l') {
/* 64 bit number */
#if defined(_WIN32)
if (q >= fmtbuf + sizeof(fmtbuf) - 3)
goto invalid;
q[2] = q[-1];
q[-1] = 'I';
q[0] = '6';
q[1] = '4';
q[3] = '\0';
dbuf_printf_fun(&dbuf, fmtbuf, (int64_t)int64_arg);
#else
if (q >= fmtbuf + sizeof(fmtbuf) - 2)
goto invalid;
q[1] = q[-1];
q[-1] = q[0] = 'l';
q[2] = '\0';
dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg);
#endif
} else {
dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg);
}
break;
case 's':
if (i >= argc)
goto missing;
/* XXX: handle strings containing null characters */
string_arg = JS_ToCString(ctx, argv[i++]);
if (!string_arg)
goto fail;
dbuf_printf_fun(&dbuf, fmtbuf, string_arg);
JS_FreeCString(ctx, string_arg);
break;
case 'e':
case 'f':
case 'g':
case 'a':
case 'E':
case 'F':
case 'G':
case 'A':
if (i >= argc)
goto missing;
if (JS_ToFloat64(ctx, &double_arg, argv[i++]))
goto fail;
dbuf_printf_fun(&dbuf, fmtbuf, double_arg);
break;
case '%':
dbuf_putc(&dbuf, '%');
break;
default:
/* XXX: should support an extension mechanism */
invalid:
JS_ThrowTypeError(ctx, "invalid conversion specifier in format string");
goto fail;
missing:
JS_ThrowReferenceError(ctx, "missing argument for conversion specifier");
goto fail;
}
}
JS_FreeCString(ctx, fmt_str);
}
if (dbuf.error) {
res = JS_ThrowOutOfMemory(ctx);
} else {
if (fp) {
len = fwrite(dbuf.buf, 1, dbuf.size, fp);
res = JS_NewInt32(ctx, len);
} else {
res = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size);
}
}
dbuf_free(&dbuf);
return res;
fail:
dbuf_free(&dbuf);
return JS_EXCEPTION;
}
uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename)
{
FILE *f;
uint8_t *buf;
size_t buf_len;
long lret;
f = fopen(filename, "rb");
if (!f)
return NULL;
if (fseek(f, 0, SEEK_END) < 0)
goto fail;
lret = ftell(f);
if (lret < 0)
goto fail;
/* XXX: on Linux, ftell() return LONG_MAX for directories */
if (lret == LONG_MAX) {
errno = EISDIR;
goto fail;
}
buf_len = lret;
if (fseek(f, 0, SEEK_SET) < 0)
goto fail;
if (ctx)
buf = js_malloc(ctx, buf_len + 1);
else
buf = malloc(buf_len + 1);
if (!buf)
goto fail;
if (fread(buf, 1, buf_len, f) != buf_len) {
errno = EIO;
if (ctx)
js_free(ctx, buf);
else
free(buf);
fail:
fclose(f);
return NULL;
}
buf[buf_len] = '\0';
fclose(f);
*pbuf_len = buf_len;
return buf;
}
/* load and evaluate a file */
static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
uint8_t *buf;
const char *filename;
JSValue ret;
size_t buf_len;
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
return JS_EXCEPTION;
buf = js_load_file(ctx, &buf_len, filename);
if (!buf) {
JS_ThrowReferenceError(ctx, "could not load '%s'", filename);
JS_FreeCString(ctx, filename);
return JS_EXCEPTION;
}
ret = JS_Eval(ctx, (char *)buf, buf_len, filename,
JS_EVAL_TYPE_GLOBAL);
js_free(ctx, buf);
JS_FreeCString(ctx, filename);
return ret;
}
/* load a file as a UTF-8 encoded string */
static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
uint8_t *buf;
const char *filename;
JSValue ret;
size_t buf_len;
filename = JS_ToCString(ctx, argv[0]);
if (!filename)
return JS_EXCEPTION;
buf = js_load_file(ctx, &buf_len, filename);
JS_FreeCString(ctx, filename);
if (!buf)
return JS_NULL;
ret = JS_NewStringLen(ctx, (char *)buf, buf_len);
js_free(ctx, buf);
return ret;
}
typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx,
const char *module_name);
#if defined(_WIN32)
static JSModuleDef *js_module_loader_so(JSContext *ctx,
const char *module_name)
{
JS_ThrowReferenceError(ctx, "shared library modules are not supported yet");
return NULL;
}
#else
static JSModuleDef *js_module_loader_so(JSContext *ctx,
const char *module_name)
{
JSModuleDef *m;
void *hd;
JSInitModuleFunc *init;
char *filename;
if (!strchr(module_name, '/')) {
/* must add a '/' so that the DLL is not searched in the
system library paths */
filename = js_malloc(ctx, strlen(module_name) + 2 + 1);
if (!filename)
return NULL;
strcpy(filename, "./");
strcpy(filename + 2, module_name);
} else {
filename = (char *)module_name;
}
/* C module */
hd = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
if (filename != module_name)
js_free(ctx, filename);
if (!hd) {
goto fail;
}
init = dlsym(hd, "js_init_module");
if (!init) {
goto fail;
}
m = init(ctx, module_name);
if (!m) {
fail:
if (hd)
dlclose(hd);
return NULL;
}
return m;
}
#endif /* !_WIN32 */
int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
JS_BOOL use_realpath, JS_BOOL is_main)
{
JSModuleDef *m;
char buf[PATH_MAX + 16];
JSValue meta_obj;
JSAtom module_name_atom;
const char *module_name;
assert(JS_VALUE_GET_TAG(func_val) == JS_TAG_MODULE);
m = JS_VALUE_GET_PTR(func_val);
module_name_atom = JS_GetModuleName(ctx, m);
module_name = JS_AtomToCString(ctx, module_name_atom);
JS_FreeAtom(ctx, module_name_atom);
if (!module_name)
return -1;
if (!strchr(module_name, ':')) {
strcpy(buf, "file://");
#if !defined(_WIN32)
/* realpath() cannot be used with modules compiled with qjsc
because the corresponding module source code is not
necessarily present */
if (use_realpath) {
char *res = realpath(module_name, buf + strlen(buf));
if (!res) {
JS_ThrowTypeError(ctx, "realpath failure");
JS_FreeCString(ctx, module_name);
return -1;
}
} else
#endif
{
pstrcat(buf, sizeof(buf), module_name);
}
} else {
pstrcpy(buf, sizeof(buf), module_name);
}
JS_FreeCString(ctx, module_name



Disclaimer: The above articles are added by users themselves and are only for typing and communication purposes. They do not represent the views of this website, and this website does not assume any legal responsibility. This statement is hereby made! If there is any infringement of your rights, please contact us promptly to delete it.

字符:    改为:
去打字就可以设置个性皮肤啦!(O ^ ~ ^ O)