Skip to content
Merged
Show file tree
Hide file tree
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
89 changes: 69 additions & 20 deletions api-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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), "<input>", 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)
Expand All @@ -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), "<input>", JS_EVAL_TYPE_GLOBAL);
JSValue ret = eval(ctx, code);
assert(time > MAX_TIME);
assert(JS_IsException(ret));
JS_FreeValue(ctx, ret);
Expand All @@ -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), "<input>", JS_EVAL_TYPE_GLOBAL);
JSValue ret = eval(ctx, code);
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(JS_IsJobPending(rt));
Expand Down Expand Up @@ -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), "<input>", JS_EVAL_TYPE_GLOBAL);
JSValue ret = eval(ctx, code);
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(JS_IsJobPending(rt));
Expand All @@ -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);
}
Expand All @@ -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));
Expand Down Expand Up @@ -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), "<input>", 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), "<input>", 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), "<input>", JS_EVAL_TYPE_GLOBAL);
JSValue ret_test2 = eval(ctx, test_code);
assert(!JS_IsException(ret_test2));
JS_RunGC(rt);
JSMemoryUsage memory_usage2;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -650,6 +698,7 @@ static void slice_string_tocstring(void)

int main(void)
{
cfunctions();
sync_call();
async_call();
async_call_stack_overflow();
Expand Down
40 changes: 29 additions & 11 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions quickjs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down