Skip to content

Commit d01ca44

Browse files
authored
Add JS_NewCFunctionData2 (#1195)
Fixes: #1190
1 parent cf0c52c commit d01ca44

File tree

3 files changed

+102
-31
lines changed

3 files changed

+102
-31
lines changed

api-test.c

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,60 @@
77
#include "quickjs.h"
88
#include "cutils.h"
99

10+
static JSValue eval(JSContext *ctx, const char *code)
11+
{
12+
return JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_GLOBAL);
13+
}
14+
15+
static void cfunctions(void)
16+
{
17+
uint32_t length;
18+
const char *s;
19+
JSValue ret;
20+
21+
JSRuntime *rt = JS_NewRuntime();
22+
JSContext *ctx = JS_NewContext(rt);
23+
JSValue cfunc = JS_NewCFunction(ctx, NULL, "cfunc", 42);
24+
JSValue cfuncdata =
25+
JS_NewCFunctionData2(ctx, NULL, "cfuncdata", /*length*/1337, /*magic*/0,
26+
/*data_len*/0, NULL);
27+
JSValue global = JS_GetGlobalObject(ctx);
28+
JS_SetPropertyStr(ctx, global, "cfunc", cfunc);
29+
JS_SetPropertyStr(ctx, global, "cfuncdata", cfuncdata);
30+
JS_FreeValue(ctx, global);
31+
32+
ret = eval(ctx, "cfunc.name");
33+
assert(!JS_IsException(ret));
34+
assert(JS_IsString(ret));
35+
s = JS_ToCString(ctx, ret);
36+
JS_FreeValue(ctx, ret);
37+
assert(s);
38+
assert(!strcmp(s, "cfunc"));
39+
JS_FreeCString(ctx, s);
40+
ret = eval(ctx, "cfunc.length");
41+
assert(!JS_IsException(ret));
42+
assert(JS_IsNumber(ret));
43+
assert(0 == JS_ToUint32(ctx, &length, ret));
44+
assert(length == 42);
45+
46+
ret = eval(ctx, "cfuncdata.name");
47+
assert(!JS_IsException(ret));
48+
assert(JS_IsString(ret));
49+
s = JS_ToCString(ctx, ret);
50+
JS_FreeValue(ctx, ret);
51+
assert(s);
52+
assert(!strcmp(s, "cfuncdata"));
53+
JS_FreeCString(ctx, s);
54+
ret = eval(ctx, "cfuncdata.length");
55+
assert(!JS_IsException(ret));
56+
assert(JS_IsNumber(ret));
57+
assert(0 == JS_ToUint32(ctx, &length, ret));
58+
assert(length == 1337);
59+
60+
JS_FreeContext(ctx);
61+
JS_FreeRuntime(rt);
62+
}
63+
1064
#define MAX_TIME 10
1165

1266
static int timeout_interrupt_handler(JSRuntime *rt, void *opaque)
@@ -30,7 +84,7 @@ static void sync_call(void)
3084
JSContext *ctx = JS_NewContext(rt);
3185
int time = 0;
3286
JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
33-
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_GLOBAL);
87+
JSValue ret = eval(ctx, code);
3488
assert(time > MAX_TIME);
3589
assert(JS_IsException(ret));
3690
JS_FreeValue(ctx, ret);
@@ -57,7 +111,7 @@ static void async_call(void)
57111
JSContext *ctx = JS_NewContext(rt);
58112
int time = 0;
59113
JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
60-
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_GLOBAL);
114+
JSValue ret = eval(ctx, code);
61115
assert(!JS_IsException(ret));
62116
JS_FreeValue(ctx, ret);
63117
assert(JS_IsJobPending(rt));
@@ -104,7 +158,7 @@ static void async_call_stack_overflow(void)
104158
JSValue global = JS_GetGlobalObject(ctx);
105159
JS_SetPropertyStr(ctx, global, "save_value", JS_NewCFunction(ctx, save_value, "save_value", 1));
106160
JS_FreeValue(ctx, global);
107-
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_GLOBAL);
161+
JSValue ret = eval(ctx, code);
108162
assert(!JS_IsException(ret));
109163
JS_FreeValue(ctx, ret);
110164
assert(JS_IsJobPending(rt));
@@ -127,20 +181,17 @@ static void raw_context_global_var(void)
127181
JSContext *ctx = JS_NewContextRaw(rt);
128182
JS_AddIntrinsicEval(ctx);
129183
{
130-
static const char code[] = "globalThis";
131-
JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
184+
JSValue ret = eval(ctx, "globalThis");
132185
assert(JS_IsException(ret));
133186
JS_FreeValue(ctx, ret);
134187
}
135188
{
136-
static const char code[] = "var x = 42";
137-
JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
189+
JSValue ret = eval(ctx, "var x = 42");
138190
assert(JS_IsUndefined(ret));
139191
JS_FreeValue(ctx, ret);
140192
}
141193
{
142-
static const char code[] = "function f() {}";
143-
JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
194+
JSValue ret = eval(ctx, "function f() {}");
144195
assert(JS_IsUndefined(ret));
145196
JS_FreeValue(ctx, ret);
146197
}
@@ -153,15 +204,13 @@ static void is_array(void)
153204
JSRuntime *rt = JS_NewRuntime();
154205
JSContext *ctx = JS_NewContext(rt);
155206
{
156-
static const char code[] = "[]";
157-
JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
207+
JSValue ret = eval(ctx, "[]");
158208
assert(!JS_IsException(ret));
159209
assert(JS_IsArray(ret));
160210
JS_FreeValue(ctx, ret);
161211
}
162212
{
163-
static const char code[] = "new Proxy([], {})";
164-
JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
213+
JSValue ret = eval(ctx, "new Proxy([], {})");
165214
assert(!JS_IsException(ret));
166215
assert(!JS_IsArray(ret));
167216
assert(JS_IsProxy(ret));
@@ -285,17 +334,17 @@ function addItem() { \
285334
JSRuntime *rt = JS_NewRuntime();
286335
JSContext *ctx = JS_NewContext(rt);
287336

288-
JSValue ret = JS_Eval(ctx, init_code, strlen(init_code), "<input>", JS_EVAL_TYPE_GLOBAL);
337+
JSValue ret = eval(ctx, init_code);
289338
assert(!JS_IsException(ret));
290339

291-
JSValue ret_test = JS_Eval(ctx, test_code, strlen(test_code), "<input>", JS_EVAL_TYPE_GLOBAL);
340+
JSValue ret_test = eval(ctx, test_code);
292341
assert(!JS_IsException(ret_test));
293342
JS_RunGC(rt);
294343
JSMemoryUsage memory_usage;
295344
JS_ComputeMemoryUsage(rt, &memory_usage);
296345

297346
for (int i = 0; i < 3; i++) {
298-
JSValue ret_test2 = JS_Eval(ctx, test_code, strlen(test_code), "<input>", JS_EVAL_TYPE_GLOBAL);
347+
JSValue ret_test2 = eval(ctx, test_code);
299348
assert(!JS_IsException(ret_test2));
300349
JS_RunGC(rt);
301350
JSMemoryUsage memory_usage2;
@@ -588,7 +637,7 @@ static void global_object_prototype(void)
588637
assert(res == true);
589638
JS_FreeValue(ctx, global_object);
590639
JS_FreeValue(ctx, proto);
591-
ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
640+
ret = eval(ctx, code);
592641
assert(!JS_IsException(ret));
593642
assert(JS_IsNumber(ret));
594643
res = JS_ToInt32(ctx, &answer, ret);
@@ -619,7 +668,7 @@ static void global_object_prototype(void)
619668
assert(res == true);
620669
JS_FreeValue(ctx, global_object);
621670
JS_FreeValue(ctx, proto);
622-
ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
671+
ret = eval(ctx, code);
623672
assert(!JS_IsException(ret));
624673
assert(JS_IsNumber(ret));
625674
res = JS_ToInt32(ctx, &answer, ret);
@@ -636,8 +685,7 @@ static void slice_string_tocstring(void)
636685
{
637686
JSRuntime *rt = JS_NewRuntime();
638687
JSContext *ctx = JS_NewContext(rt);
639-
static const char code[] = "'.'.repeat(16384).slice(1, -1)";
640-
JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
688+
JSValue ret = eval(ctx, "'.'.repeat(16384).slice(1, -1)");
641689
assert(!JS_IsException(ret));
642690
assert(JS_IsString(ret));
643691
const char *str = JS_ToCString(ctx, ret);
@@ -650,6 +698,7 @@ static void slice_string_tocstring(void)
650698

651699
int main(void)
652700
{
701+
cfunctions();
653702
sync_call();
654703
async_call();
655704
async_call_stack_overflow();

quickjs.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5377,12 +5377,13 @@ JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
53775377
cproto == JS_CFUNC_constructor_magic ||
53785378
cproto == JS_CFUNC_constructor_or_func ||
53795379
cproto == JS_CFUNC_constructor_or_func_magic);
5380-
if (!name)
5381-
name = "";
5382-
name_atom = JS_NewAtom(ctx, name);
5383-
if (name_atom == JS_ATOM_NULL) {
5384-
JS_FreeValue(ctx, func_obj);
5385-
return JS_EXCEPTION;
5380+
name_atom = JS_ATOM_empty_string;
5381+
if (name && *name) {
5382+
name_atom = JS_NewAtom(ctx, name);
5383+
if (name_atom == JS_ATOM_NULL) {
5384+
JS_FreeValue(ctx, func_obj);
5385+
return JS_EXCEPTION;
5386+
}
53865387
}
53875388
js_function_set_properties(ctx, func_obj, name_atom, length);
53885389
JS_FreeAtom(ctx, name_atom);
@@ -5454,11 +5455,13 @@ static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
54545455
return s->func(ctx, this_val, argc, arg_buf, s->magic, vc(s->data));
54555456
}
54565457

5457-
JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
5458-
int length, int magic, int data_len,
5459-
JSValueConst *data)
5458+
JSValue JS_NewCFunctionData2(JSContext *ctx, JSCFunctionData *func,
5459+
const char *name,
5460+
int length, int magic, int data_len,
5461+
JSValueConst *data)
54605462
{
54615463
JSCFunctionDataRecord *s;
5464+
JSAtom name_atom;
54625465
JSValue func_obj;
54635466
int i;
54645467

@@ -5478,11 +5481,26 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
54785481
for(i = 0; i < data_len; i++)
54795482
s->data[i] = js_dup(data[i]);
54805483
JS_SetOpaqueInternal(func_obj, s);
5481-
js_function_set_properties(ctx, func_obj,
5482-
JS_ATOM_empty_string, length);
5484+
name_atom = JS_ATOM_empty_string;
5485+
if (name && *name) {
5486+
name_atom = JS_NewAtom(ctx, name);
5487+
if (name_atom == JS_ATOM_NULL) {
5488+
JS_FreeValue(ctx, func_obj);
5489+
return JS_EXCEPTION;
5490+
}
5491+
}
5492+
js_function_set_properties(ctx, func_obj, name_atom, length);
5493+
JS_FreeAtom(ctx, name_atom);
54835494
return func_obj;
54845495
}
54855496

5497+
JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
5498+
int length, int magic, int data_len,
5499+
JSValueConst *data)
5500+
{
5501+
return JS_NewCFunctionData2(ctx, func, NULL, length, magic, data_len, data);
5502+
}
5503+
54865504
static JSContext *js_autoinit_get_realm(JSProperty *pr)
54875505
{
54885506
return (JSContext *)(pr->u.init.realm_and_id & ~3);

quickjs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,10 @@ JS_EXTERN JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
11591159
JS_EXTERN JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
11601160
int length, int magic, int data_len,
11611161
JSValueConst *data);
1162+
JS_EXTERN JSValue JS_NewCFunctionData2(JSContext *ctx, JSCFunctionData *func,
1163+
const char *name,
1164+
int length, int magic, int data_len,
1165+
JSValueConst *data);
11621166

11631167
static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func,
11641168
const char *name, int length)

0 commit comments

Comments
 (0)