Skip to content

Small fixes and additional functions #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 54 additions & 8 deletions quickjs-libc.c
Original file line number Diff line number Diff line change
@@ -466,8 +466,50 @@ typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx,
static JSModuleDef *js_module_loader_so(JSContext *ctx,
const char *module_name)
{
JS_ThrowReferenceError(ctx, "shared library modules are not supported yet");
return NULL;
JSModuleDef *m;
HANDLE 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 = LoadLibrary(filename);
if (filename != module_name)
js_free(ctx, filename);
if (!hd) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s'('%s') as shared library",
module_name,filename);
goto fail;
}

init = (JSInitModuleFunc*)GetProcAddress(hd,"js_init_module");
if (!init) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found",
module_name);
goto fail;
}

m = init(ctx, module_name);
if (!m) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s': initialization error",
module_name);
fail:
if (hd)
FreeLibrary(hd);
return NULL;
}
return m;
Comment on lines -469 to +512
Copy link
Collaborator

@chqrlie chqrlie Mar 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of duplicating the whole function, I would favor using wrappers for the handle declaration, module loading, symbol lookup and module unloading, using macros:

#if defined(_WIN32)
typedef Handle lib_handle;
#define lib_open(name)  LoadLibrary(name)
#define lib_sym(hd, name)  GetProcAddress(hd, name)
#define lib_close(hd) FreeLibrary(hd)
#define lib_extension ".dll"
#else
typedef void *lib_handle;
#define lib_open(name)   dlopen(name, RTLD_NOW | RTLD_LOCAL)
#define lib_sym(hd, name)  dlsym(hd, name)
#define lib_close(hd) dlclose(hd)
#define lib_extension ".so"
#endif

}
#else
static JSModuleDef *js_module_loader_so(JSContext *ctx,
@@ -495,15 +537,13 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx,
if (filename != module_name)
js_free(ctx, filename);
if (!hd) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library",
module_name);
goto fail;
goto dlerror;
}

init = dlsym(hd, "js_init_module");
if (!init) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found",
module_name);
dlerror:
JS_ThrowReferenceError(ctx, "could not load module filename '%s': %s", module_name, dlerror());
goto fail;
}

@@ -578,7 +618,13 @@ JSModuleDef *js_module_loader(JSContext *ctx,
{
JSModuleDef *m;

if (has_suffix(module_name, ".so")) {
if (
#if !defined(_WIN32)
has_suffix(module_name, ".so")
#else
has_suffix(module_name, ".dll")
#endif
) {
m = js_module_loader_so(ctx, module_name);
} else {
size_t buf_len;
33 changes: 29 additions & 4 deletions quickjs.c
Original file line number Diff line number Diff line change
@@ -3874,6 +3874,20 @@ static JSValue string_buffer_end(StringBuffer *s)
return JS_MKPTR(JS_TAG_STRING, str);
}

JSValue JS_NewStringWLen(JSContext *ctx, size_t buf_len)
{
JSString *str;
if (buf_len <= 0) {
return JS_AtomToString(ctx, JS_ATOM_empty_string);
}
str = js_alloc_string_rt(ctx->rt, buf_len, 0);
if (unlikely(!str)){
JS_ThrowOutOfMemory(ctx);
return JS_EXCEPTION;
}
memset(str->u.str8, 0, buf_len+1);
return JS_MKPTR(JS_TAG_STRING, str);
}
Comment on lines +3877 to +3890
Copy link
Collaborator

@chqrlie chqrlie Mar 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a new API, I would modify JS_NewStringLen to accept a null pointer and initialize the allocated string with null bytes using this:

    if (buf_len <= 0) {
        return JS_AtomToString(ctx, JS_ATOM_empty_string);
    }
    if (buf == NULL) {
        JSString *str = js_alloc_string(ctx, buf_len, 0);
        if (!str)
            return JS_EXCEPTION;
        memset(str->u.str8, buf, buf_len + 1);
        return JS_MKPTR(JS_TAG_STRING, str);
    }

/* create a string from a UTF-8 buffer */
JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len)
{
@@ -3980,6 +3994,18 @@ JSValue JS_NewAtomString(JSContext *ctx, const char *str)
return val;
}

uint8_t *JS_ToCStringLenRaw(JSContext *ctx, size_t *plen, JSValueConst val)
{
if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)
{
if(plen) *plen = 0;
return NULL;
}
JSString *str = JS_VALUE_GET_STRING(val);
if(plen) *plen = str->len;
return str->u.str8;
}

Comment on lines +3997 to +4008
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one has a problem: the caller cannot determine if the string was encoded as 8-bit or 16-bit. Furthermore the name is misleading: the returned pointer is not UTF-8 encoded if the string has non-ASCII characters.

/* return (NULL, 0) if exception. */
/* return pointer into a JSString with a live ref_count */
/* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */
@@ -4929,7 +4955,7 @@ static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val)
return -1;
}

JSValue JS_NewObjectClass(JSContext *ctx, int class_id)
JSValue JS_NewObjectClass(JSContext *ctx, JSClassID class_id)
Comment on lines -4932 to +4958
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prototype must be changed in quickjs.h too.

{
return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id);
}
@@ -43229,11 +43255,10 @@ static uint64_t xorshift64star(uint64_t *pstate)
return x * 0x2545F4914F6CDD1D;
}

static int64_t date_now(void);
static void js_random_init(JSContext *ctx)
{
struct timeval tv;
gettimeofday(&tv, NULL);
ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
ctx->random_state = date_now();
/* the state must be non zero */
if (ctx->random_state == 0)
ctx->random_state = 1;
2 changes: 2 additions & 0 deletions quickjs.h
Original file line number Diff line number Diff line change
@@ -696,11 +696,13 @@ int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
/* same as JS_ToInt64() but allow BigInt */
int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val);

JSValue JS_NewStringWLen(JSContext *ctx, size_t len);
JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1);
JSValue JS_NewString(JSContext *ctx, const char *str);
JSValue JS_NewAtomString(JSContext *ctx, const char *str);
JSValue JS_ToString(JSContext *ctx, JSValueConst val);
JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val);
uint8_t *JS_ToCStringLenRaw(JSContext *ctx, size_t *plen, JSValueConst val1);
const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8);
static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1)
{