diff --git a/api-test.c b/api-test.c
index 8cbf8fac5..ebdb2a77c 100644
--- a/api-test.c
+++ b/api-test.c
@@ -7,6 +7,60 @@
#include "quickjs.h"
#include "cutils.h"
+static JSValue eval(JSContext *ctx, const char *code)
+{
+ return JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL);
+}
+
+static void cfunctions(void)
+{
+ uint32_t length;
+ const char *s;
+ JSValue ret;
+
+ JSRuntime *rt = JS_NewRuntime();
+ JSContext *ctx = JS_NewContext(rt);
+ JSValue cfunc = JS_NewCFunction(ctx, NULL, "cfunc", 42);
+ JSValue cfuncdata =
+ JS_NewCFunctionData2(ctx, NULL, "cfuncdata", /*length*/1337, /*magic*/0,
+ /*data_len*/0, NULL);
+ JSValue global = JS_GetGlobalObject(ctx);
+ JS_SetPropertyStr(ctx, global, "cfunc", cfunc);
+ JS_SetPropertyStr(ctx, global, "cfuncdata", cfuncdata);
+ JS_FreeValue(ctx, global);
+
+ ret = eval(ctx, "cfunc.name");
+ assert(!JS_IsException(ret));
+ assert(JS_IsString(ret));
+ s = JS_ToCString(ctx, ret);
+ JS_FreeValue(ctx, ret);
+ assert(s);
+ assert(!strcmp(s, "cfunc"));
+ JS_FreeCString(ctx, s);
+ ret = eval(ctx, "cfunc.length");
+ assert(!JS_IsException(ret));
+ assert(JS_IsNumber(ret));
+ assert(0 == JS_ToUint32(ctx, &length, ret));
+ assert(length == 42);
+
+ ret = eval(ctx, "cfuncdata.name");
+ assert(!JS_IsException(ret));
+ assert(JS_IsString(ret));
+ s = JS_ToCString(ctx, ret);
+ JS_FreeValue(ctx, ret);
+ assert(s);
+ assert(!strcmp(s, "cfuncdata"));
+ JS_FreeCString(ctx, s);
+ ret = eval(ctx, "cfuncdata.length");
+ assert(!JS_IsException(ret));
+ assert(JS_IsNumber(ret));
+ assert(0 == JS_ToUint32(ctx, &length, ret));
+ assert(length == 1337);
+
+ JS_FreeContext(ctx);
+ JS_FreeRuntime(rt);
+}
+
#define MAX_TIME 10
static int timeout_interrupt_handler(JSRuntime *rt, void *opaque)
@@ -30,7 +84,7 @@ static void sync_call(void)
JSContext *ctx = JS_NewContext(rt);
int time = 0;
JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
- JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, code);
assert(time > MAX_TIME);
assert(JS_IsException(ret));
JS_FreeValue(ctx, ret);
@@ -57,7 +111,7 @@ static void async_call(void)
JSContext *ctx = JS_NewContext(rt);
int time = 0;
JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
- JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, code);
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(JS_IsJobPending(rt));
@@ -104,7 +158,7 @@ static void async_call_stack_overflow(void)
JSValue global = JS_GetGlobalObject(ctx);
JS_SetPropertyStr(ctx, global, "save_value", JS_NewCFunction(ctx, save_value, "save_value", 1));
JS_FreeValue(ctx, global);
- JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, code);
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(JS_IsJobPending(rt));
@@ -127,20 +181,17 @@ static void raw_context_global_var(void)
JSContext *ctx = JS_NewContextRaw(rt);
JS_AddIntrinsicEval(ctx);
{
- static const char code[] = "globalThis";
- JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, "globalThis");
assert(JS_IsException(ret));
JS_FreeValue(ctx, ret);
}
{
- static const char code[] = "var x = 42";
- JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, "var x = 42");
assert(JS_IsUndefined(ret));
JS_FreeValue(ctx, ret);
}
{
- static const char code[] = "function f() {}";
- JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, "function f() {}");
assert(JS_IsUndefined(ret));
JS_FreeValue(ctx, ret);
}
@@ -153,15 +204,13 @@ static void is_array(void)
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
{
- static const char code[] = "[]";
- JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, "[]");
assert(!JS_IsException(ret));
assert(JS_IsArray(ret));
JS_FreeValue(ctx, ret);
}
{
- static const char code[] = "new Proxy([], {})";
- JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, "new Proxy([], {})");
assert(!JS_IsException(ret));
assert(!JS_IsArray(ret));
assert(JS_IsProxy(ret));
@@ -285,17 +334,17 @@ function addItem() { \
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
- JSValue ret = JS_Eval(ctx, init_code, strlen(init_code), "", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, init_code);
assert(!JS_IsException(ret));
- JSValue ret_test = JS_Eval(ctx, test_code, strlen(test_code), "", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret_test = eval(ctx, test_code);
assert(!JS_IsException(ret_test));
JS_RunGC(rt);
JSMemoryUsage memory_usage;
JS_ComputeMemoryUsage(rt, &memory_usage);
for (int i = 0; i < 3; i++) {
- JSValue ret_test2 = JS_Eval(ctx, test_code, strlen(test_code), "", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret_test2 = eval(ctx, test_code);
assert(!JS_IsException(ret_test2));
JS_RunGC(rt);
JSMemoryUsage memory_usage2;
@@ -588,7 +637,7 @@ static void global_object_prototype(void)
assert(res == true);
JS_FreeValue(ctx, global_object);
JS_FreeValue(ctx, proto);
- ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ ret = eval(ctx, code);
assert(!JS_IsException(ret));
assert(JS_IsNumber(ret));
res = JS_ToInt32(ctx, &answer, ret);
@@ -619,7 +668,7 @@ static void global_object_prototype(void)
assert(res == true);
JS_FreeValue(ctx, global_object);
JS_FreeValue(ctx, proto);
- ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ ret = eval(ctx, code);
assert(!JS_IsException(ret));
assert(JS_IsNumber(ret));
res = JS_ToInt32(ctx, &answer, ret);
@@ -636,8 +685,7 @@ static void slice_string_tocstring(void)
{
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
- static const char code[] = "'.'.repeat(16384).slice(1, -1)";
- JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
+ JSValue ret = eval(ctx, "'.'.repeat(16384).slice(1, -1)");
assert(!JS_IsException(ret));
assert(JS_IsString(ret));
const char *str = JS_ToCString(ctx, ret);
@@ -650,6 +698,7 @@ static void slice_string_tocstring(void)
int main(void)
{
+ cfunctions();
sync_call();
async_call();
async_call_stack_overflow();
diff --git a/quickjs.c b/quickjs.c
index 793a13e9f..e0b38c7a3 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -5377,12 +5377,13 @@ JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
cproto == JS_CFUNC_constructor_magic ||
cproto == JS_CFUNC_constructor_or_func ||
cproto == JS_CFUNC_constructor_or_func_magic);
- if (!name)
- name = "";
- name_atom = JS_NewAtom(ctx, name);
- if (name_atom == JS_ATOM_NULL) {
- JS_FreeValue(ctx, func_obj);
- return JS_EXCEPTION;
+ name_atom = JS_ATOM_empty_string;
+ if (name && *name) {
+ name_atom = JS_NewAtom(ctx, name);
+ if (name_atom == JS_ATOM_NULL) {
+ JS_FreeValue(ctx, func_obj);
+ return JS_EXCEPTION;
+ }
}
js_function_set_properties(ctx, func_obj, name_atom, length);
JS_FreeAtom(ctx, name_atom);
@@ -5454,11 +5455,13 @@ static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
return s->func(ctx, this_val, argc, arg_buf, s->magic, vc(s->data));
}
-JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
- int length, int magic, int data_len,
- JSValueConst *data)
+JSValue JS_NewCFunctionData2(JSContext *ctx, JSCFunctionData *func,
+ const char *name,
+ int length, int magic, int data_len,
+ JSValueConst *data)
{
JSCFunctionDataRecord *s;
+ JSAtom name_atom;
JSValue func_obj;
int i;
@@ -5478,11 +5481,26 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
for(i = 0; i < data_len; i++)
s->data[i] = js_dup(data[i]);
JS_SetOpaqueInternal(func_obj, s);
- js_function_set_properties(ctx, func_obj,
- JS_ATOM_empty_string, length);
+ name_atom = JS_ATOM_empty_string;
+ if (name && *name) {
+ name_atom = JS_NewAtom(ctx, name);
+ if (name_atom == JS_ATOM_NULL) {
+ JS_FreeValue(ctx, func_obj);
+ return JS_EXCEPTION;
+ }
+ }
+ js_function_set_properties(ctx, func_obj, name_atom, length);
+ JS_FreeAtom(ctx, name_atom);
return func_obj;
}
+JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
+ int length, int magic, int data_len,
+ JSValueConst *data)
+{
+ return JS_NewCFunctionData2(ctx, func, NULL, length, magic, data_len, data);
+}
+
static JSContext *js_autoinit_get_realm(JSProperty *pr)
{
return (JSContext *)(pr->u.init.realm_and_id & ~3);
diff --git a/quickjs.h b/quickjs.h
index dadd8d059..1359a07e9 100644
--- a/quickjs.h
+++ b/quickjs.h
@@ -1159,6 +1159,10 @@ JS_EXTERN JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
JS_EXTERN JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
int length, int magic, int data_len,
JSValueConst *data);
+JS_EXTERN JSValue JS_NewCFunctionData2(JSContext *ctx, JSCFunctionData *func,
+ const char *name,
+ int length, int magic, int data_len,
+ JSValueConst *data);
static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func,
const char *name, int length)