fixed function arity

This commit is contained in:
2026-01-25 13:51:34 -06:00
parent 802c94085b
commit 8325253f1a
6 changed files with 223 additions and 116 deletions

View File

@@ -686,7 +686,7 @@ typedef enum {
typedef struct JSFunction {
JSGCObjectHeader header; /* must come first */
JSAtom name;
uint8_t length;
uint16_t length; /* arity: max allowed arguments */
uint8_t kind;
uint8_t free_mark : 1;
union {
@@ -4986,7 +4986,7 @@ JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
typedef struct JSCFunctionDataRecord {
JSCFunctionData *func;
uint8_t length;
uint16_t length; /* arity: max allowed arguments */
uint8_t data_len;
uint16_t magic;
JSValue data[0];
@@ -10133,7 +10133,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc,
if (name_atom == JS_ATOM_NULL)
name_atom = JS_ATOM_empty_string;
f->name = JS_DupAtom(ctx, name_atom);
f->length = b->defined_arg_count;
f->length = b->arg_count; /* arity = total parameter count */
return func_obj;
fail:
/* bfunc is freed when func_obj is freed */
@@ -10263,6 +10263,19 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
ret_val = JS_NewFloat64(ctx, func.f_f_f(d1, d2));
}
break;
/* Fixed-arity fast paths - direct call without argc/argv marshaling */
case JS_CFUNC_0:
ret_val = func.f0(ctx, this_obj);
break;
case JS_CFUNC_1:
ret_val = func.f1(ctx, this_obj, arg_buf[0]);
break;
case JS_CFUNC_2:
ret_val = func.f2(ctx, this_obj, arg_buf[0], arg_buf[1]);
break;
case JS_CFUNC_3:
ret_val = func.f3(ctx, this_obj, arg_buf[0], arg_buf[1], arg_buf[2]);
break;
default:
abort();
}
@@ -10436,10 +10449,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
return JS_ThrowTypeError(caller_ctx, "not a function");
}
f = JS_VALUE_GET_FUNCTION(func_obj);
/* Strict arity enforcement: too many arguments throws */
if (unlikely(argc > f->length)) {
char buf[ATOM_GET_STR_BUF_SIZE];
return JS_ThrowTypeError(caller_ctx, "too many arguments for %s: expected %d, got %d", JS_AtomGetStr(caller_ctx,buf, ATOM_GET_STR_BUF_SIZE, f->name), f->length, argc);
}
switch (f->kind) {
case JS_FUNC_KIND_C:
return js_call_c_function(caller_ctx, func_obj, this_obj, argc,
(JSValueConst *)argv);
(JSValueConst *)argv);
case JS_FUNC_KIND_BOUND:
return js_call_bound_function(caller_ctx, func_obj, this_obj, argc,
(JSValueConst *)argv);
@@ -10985,6 +11003,16 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
scope_idx = get_u16(pc) + ARG_SCOPE_END;
pc += 2;
sf->cur_pc = pc;
/* Fast path: check arity before building arg list */
if (JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_FUNCTION &&
JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_ARRAY) {
JSFunction *callee = JS_VALUE_GET_FUNCTION(sp[-2]);
JSArray *arr = JS_VALUE_GET_ARRAY(sp[-1]);
if (unlikely(arr->len > callee->length)) {
JS_ThrowTypeError(ctx, "too many arguments");
goto exception;
}
}
tab = build_arg_list(ctx, &len, sp[-1]);
if (!tab)
goto exception;
@@ -22070,7 +22098,6 @@ static __exception int js_parse_function_decl2(JSParseState *s,
JSFunctionDef *fd = s->cur_func;
BOOL is_expr;
int func_idx, lexical_func_idx = -1;
BOOL has_opt_arg;
BOOL create_func_var = FALSE;
is_expr = (func_type != JS_PARSE_FUNC_STATEMENT &&
@@ -22154,7 +22181,6 @@ static __exception int js_parse_function_decl2(JSParseState *s,
/* parse arguments */
fd->has_simple_parameter_list = TRUE;
fd->has_parameter_expressions = FALSE;
has_opt_arg = FALSE;
if (func_type == JS_PARSE_FUNC_ARROW && s->token.val == TOK_IDENT) {
JSAtom name;
if (s->token.u.ident.is_reserved) {
@@ -22164,7 +22190,6 @@ static __exception int js_parse_function_decl2(JSParseState *s,
name = s->token.u.ident.atom;
if (add_arg(ctx, fd, name) < 0)
goto fail;
fd->defined_arg_count = 1;
} else if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
if (s->token.val == '(') {
int skip_bits;
@@ -22199,10 +22224,6 @@ static __exception int js_parse_function_decl2(JSParseState *s,
has_initializer = js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, TRUE, FALSE);
if (has_initializer < 0)
goto fail;
if (has_initializer)
has_opt_arg = TRUE;
if (!has_opt_arg)
fd->defined_arg_count++;
} else if (s->token.val == TOK_IDENT) {
if (s->token.u.ident.is_reserved) {
js_parse_error_reserved_identifier(s);
@@ -22224,7 +22245,6 @@ static __exception int js_parse_function_decl2(JSParseState *s,
int label;
fd->has_simple_parameter_list = FALSE;
has_opt_arg = TRUE;
if (next_token(s))
goto fail;
@@ -22248,9 +22268,6 @@ static __exception int js_parse_function_decl2(JSParseState *s,
emit_atom(s, name);
emit_u16(s, fd->scope_level);
} else {
if (!has_opt_arg) {
fd->defined_arg_count++;
}
if (fd->has_parameter_expressions) {
/* copy the argument to the argument scope */
emit_op(s, OP_get_arg);
@@ -22276,6 +22293,8 @@ static __exception int js_parse_function_decl2(JSParseState *s,
goto fail;
}
}
/* Explicit arity: defined_arg_count == arg_count always */
fd->defined_arg_count = fd->arg_count;
if (fd->has_parameter_expressions) {
int idx;
@@ -24518,14 +24537,22 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
JSValueConst this_arg, array_arg;
uint32_t len;
JSValue *tab, ret;
JSFunction *f;
if (check_function(ctx, this_val))
return JS_EXCEPTION;
f = JS_VALUE_GET_FUNCTION(this_val);
this_arg = argv[0];
array_arg = argv[1];
if (JS_VALUE_GET_TAG(array_arg) == JS_TAG_NULL && magic != 2) {
return JS_Call(ctx, this_val, this_arg, 0, NULL);
}
/* Fast path: check arity before building arg list */
if (JS_VALUE_GET_TAG(array_arg) == JS_TAG_ARRAY) {
JSArray *arr = JS_VALUE_GET_ARRAY(array_arg);
if (unlikely(arr->len > f->length))
return JS_ThrowTypeError(ctx, "too many arguments");
}
tab = build_arg_list(ctx, &len, array_arg);
if (!tab)
return JS_EXCEPTION;
@@ -27872,6 +27899,8 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
if (JS_IsFunction(ctx, argv[1])) {
/* Map */
JSValueConst func = argv[1];
int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length;
int reverse = argc > 2 && JS_ToBool(ctx, argv[2]);
JSValue exit_val = argc > 3 ? argv[3] : JS_NULL;
@@ -27886,10 +27915,15 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, result);
return JS_EXCEPTION;
}
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
JSValue val = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[0]);
JS_FreeValue(ctx, args[1]);
JSValue val;
if (arity >= 2) {
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
val = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
} else {
val = JS_Call(ctx, func, JS_NULL, 1, &item);
}
JS_FreeValue(ctx, item);
if (JS_IsException(val)) {
JS_FreeValue(ctx, result);
return JS_EXCEPTION;
@@ -27908,10 +27942,15 @@ static JSValue js_cell_array(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, result);
return JS_EXCEPTION;
}
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
JSValue val = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[0]);
JS_FreeValue(ctx, args[1]);
JSValue val;
if (arity >= 2) {
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
val = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
} else {
val = JS_Call(ctx, func, JS_NULL, 1, &item);
}
JS_FreeValue(ctx, item);
if (JS_IsException(val)) {
JS_FreeValue(ctx, result);
return JS_EXCEPTION;
@@ -28360,14 +28399,22 @@ static JSValue js_cell_array_for(JSContext *ctx, JSValueConst this_val,
int reverse = argc > 2 && JS_ToBool(ctx, argv[2]);
JSValue exit_val = argc > 3 ? argv[3] : JS_NULL;
/* Determine function arity */
int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length;
if (reverse) {
for (int64_t i = len - 1; i >= 0; i--) {
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
if (JS_IsException(item)) return JS_EXCEPTION;
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
JSValue result = JS_Call(ctx, func, JS_NULL, 2, args);
JSValue result;
if (arity == 1) {
result = JS_Call(ctx, func, JS_NULL, 1, &item);
} else {
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
result = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
}
JS_FreeValue(ctx, item);
JS_FreeValue(ctx, args[1]);
if (JS_IsException(result)) return JS_EXCEPTION;
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
return result;
@@ -28378,10 +28425,15 @@ static JSValue js_cell_array_for(JSContext *ctx, JSValueConst this_val,
for (int64_t i = 0; i < len; i++) {
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
if (JS_IsException(item)) return JS_EXCEPTION;
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
JSValue result = JS_Call(ctx, func, JS_NULL, 2, args);
JSValue result;
if (arity == 1) {
result = JS_Call(ctx, func, JS_NULL, 1, &item);
} else {
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
result = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
}
JS_FreeValue(ctx, item);
JS_FreeValue(ctx, args[1]);
if (JS_IsException(result)) return JS_EXCEPTION;
if (!JS_IsNull(exit_val) && js_strict_eq(ctx, result, exit_val)) {
return result;
@@ -28443,14 +28495,21 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val,
/* Use function predicate */
JSValueConst func = argv[1];
int arity = (JSFunction*)JS_VALUE_GET_FUNCTION(argv[1])->length;
if (reverse) {
for (int64_t i = from; i >= 0; i--) {
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
if (JS_IsException(item)) return JS_EXCEPTION;
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
JSValue result = JS_Call(ctx, func, JS_NULL, 2, args);
JSValue result;
if (arity == 2) {
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
result = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
} else {
result = JS_Call(ctx, func, JS_NULL, 1, &item);
}
JS_FreeValue(ctx, item);
JS_FreeValue(ctx, args[1]);
if (JS_IsException(result)) return JS_EXCEPTION;
if (JS_ToBool(ctx, result)) {
JS_FreeValue(ctx, result);
@@ -28462,10 +28521,16 @@ static JSValue js_cell_array_find(JSContext *ctx, JSValueConst this_val,
for (int64_t i = from; i < len; i++) {
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
if (JS_IsException(item)) return JS_EXCEPTION;
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
JSValue result = JS_Call(ctx, func, JS_NULL, 2, args);
JSValue result;
if (arity == 2) {
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
result = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
} else {
result = JS_Call(ctx, func, JS_NULL, 1, &item);
}
JS_FreeValue(ctx, item);
JS_FreeValue(ctx, args[1]);
if (JS_IsException(result)) return JS_EXCEPTION;
if (JS_ToBool(ctx, result)) {
JS_FreeValue(ctx, result);
@@ -28495,6 +28560,8 @@ static JSValue js_cell_array_filter(JSContext *ctx, JSValueConst this_val,
JSValue result = JS_NewArray(ctx);
if (JS_IsException(result)) return result;
int arity = ((JSFunction*)JS_VALUE_GET_FUNCTION(func))->length;
int64_t out_idx = 0;
for (int64_t i = 0; i < len; i++) {
JSValue item = JS_GetPropertyInt64(ctx, arr, i);
@@ -28502,9 +28569,16 @@ static JSValue js_cell_array_filter(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, result);
return JS_EXCEPTION;
}
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
JSValue val = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
JSValue val;
if (arity == 0) {
val = JS_Call(ctx, func, JS_NULL, 0, NULL);
} else if (arity == 1) {
val = JS_Call(ctx, func, JS_NULL, 1, &item);
} else {
JSValue args[2] = { item, JS_NewInt64(ctx, i) };
val = JS_Call(ctx, func, JS_NULL, 2, args);
JS_FreeValue(ctx, args[1]);
}
if (JS_IsException(val)) {
JS_FreeValue(ctx, item);
JS_FreeValue(ctx, result);
@@ -28848,7 +28922,7 @@ static JSValue js_cell_object(JSContext *ctx, JSValueConst this_val,
* fn function and sub-functions
* ---------------------------------------------------------------------------- */
/* fn.apply(func, args) */
/* fn.apply(func, args) - arity is enforced in JS_CallInternal */
static JSValue js_cell_fn_apply(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -28871,19 +28945,6 @@ static JSValue js_cell_fn_apply(JSContext *ctx, JSValueConst this_val,
if (js_get_length64(ctx, &len, args_val))
return JS_EXCEPTION;
/* Check arity */
JSValue func_len = JS_GetPropertyStr(ctx, func, "length");
if (!JS_IsException(func_len)) {
int arity;
if (!JS_ToInt32(ctx, &arity, func_len)) {
if (len > arity) {
JS_FreeValue(ctx, func_len);
return JS_ThrowTypeError(ctx, "fn.apply: too many arguments");
}
}
JS_FreeValue(ctx, func_len);
}
JSValue *args = js_malloc(ctx, sizeof(JSValue) * (len > 0 ? len : 1));
if (!args) return JS_EXCEPTION;
@@ -29221,22 +29282,22 @@ static JSValue js_blob_w32(JSContext *ctx, JSValueConst this_val,
}
/* blob.wf(value) - write float */
static JSValue js_blob_wf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
static JSValue js_blob_wf(JSContext *ctx, JSValueConst this_val, JSValueConst arg0)
{
if (argc < 1) return JS_ThrowTypeError(ctx, "wf(value) requires 1 argument");
if (JS_IsNull(arg0)) return JS_ThrowTypeError(ctx, "wf(value) requires 1 argument");
blob *bd = js_get_blob(ctx, this_val);
if (!bd) return JS_ThrowTypeError(ctx, "wf: not called on a blob");
float f;
int tag = JS_VALUE_GET_TAG(argv[0]);
int tag = JS_VALUE_GET_TAG(arg0);
if (tag == JS_TAG_INT) {
f = (float)JS_VALUE_GET_INT(argv[0]);
f = (float)JS_VALUE_GET_INT(arg0);
} else if (tag == JS_TAG_FLOAT64) {
f = (float)JS_VALUE_GET_FLOAT64(argv[0]);
f = (float)JS_VALUE_GET_FLOAT64(arg0);
} else {
double d;
if (JS_ToFloat64(ctx, &d, argv[0]) < 0) return JS_EXCEPTION;
if (JS_ToFloat64(ctx, &d, arg0) < 0) return JS_EXCEPTION;
f = (float)d;
}
@@ -29409,7 +29470,7 @@ static const JSCFunctionListEntry js_blob_proto_funcs[] = {
JS_CFUNC_DEF("write_fit", 2, js_blob_write_fit),
JS_CFUNC_DEF("write_text", 1, js_blob_write_text),
JS_CFUNC_DEF("write_pad", 1, js_blob_write_pad),
JS_CFUNC_DEF("wf", 1, js_blob_wf),
JS_CFUNC1_DEF("wf", js_blob_wf),
JS_CFUNC_DEF("w16", 1, js_blob_w16),
JS_CFUNC_DEF("w32", 1, js_blob_w32),
@@ -29922,7 +29983,7 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
* call() function - call a function with explicit this and arguments
* ============================================================================ */
/* call(func, this_val, ...args) */
/* call(func, this_val, args_array) */
static JSValue js_cell_call(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -29937,10 +29998,20 @@ static JSValue js_cell_call(JSContext *ctx, JSValueConst this_val,
if (argc >= 2)
this_arg = argv[1];
int call_argc = argc > 2 ? argc - 2 : 0;
JSValueConst *call_argv = call_argc > 0 ? &argv[2] : NULL;
if (argc < 3 || JS_IsNull(argv[2]))
return JS_Call(ctx, func, this_arg, 0, NULL);
return JS_Call(ctx, func, this_arg, call_argc, call_argv);
if (!JS_IsArray(ctx, argv[2]))
return JS_ThrowTypeError(ctx, "third argument must be an array");
uint32_t len;
JSValue *tab = build_arg_list(ctx, &len, argv[2]);
if (!tab)
return JS_EXCEPTION;
JSValue ret = JS_Call(ctx, func, this_arg, len, (JSValueConst *)tab);
free_arg_list(ctx, tab, len);
return ret;
}
/* ============================================================================
@@ -30199,7 +30270,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
/* Cell Script global functions: text, number, array, object, fn */
{
JSValue text_func = JS_NewCFunction(ctx, js_cell_text, "text", 2);
JSValue text_func = JS_NewCFunction(ctx, js_cell_text, "text", 3);
JS_SetPropertyStr(ctx, ctx->global_obj, "text", text_func);
JSValue number_func = JS_NewCFunction(ctx, js_cell_number, "number", 2);
@@ -30267,7 +30338,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_SetPropertyStr(ctx, ctx->global_obj, "apply",
JS_NewCFunction(ctx, js_cell_fn_apply, "apply", 2));
JS_SetPropertyStr(ctx, ctx->global_obj, "replace",
JS_NewCFunction(ctx, js_cell_text_replace, "replace", 2));
JS_NewCFunction(ctx, js_cell_text_replace, "replace", 4));
JS_SetPropertyStr(ctx, ctx->global_obj, "lower",
JS_NewCFunction(ctx, js_cell_text_lower, "lower", 1));
JS_SetPropertyStr(ctx, ctx->global_obj, "upper",
@@ -30279,7 +30350,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_SetPropertyStr(ctx, ctx->global_obj, "search",
JS_NewCFunction(ctx, js_cell_text_search, "search", 3));
JS_SetPropertyStr(ctx, ctx->global_obj, "extract",
JS_NewCFunction(ctx, js_cell_text_extract, "extract", 3));
JS_NewCFunction(ctx, js_cell_text_extract, "extract", 4));
JS_SetPropertyStr(ctx, ctx->global_obj, "reduce",
JS_NewCFunction(ctx, js_cell_array_reduce, "reduce", 4));
JS_SetPropertyStr(ctx, ctx->global_obj, "arrfor",
@@ -30309,9 +30380,9 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_SetPropertyStr(ctx, ctx->global_obj, "trunc",
JS_NewCFunction(ctx, js_cell_number_trunc, "trunc", 2));
JS_SetPropertyStr(ctx, ctx->global_obj, "min",
JS_NewCFunction(ctx, js_cell_number_min, "min", 0));
JS_NewCFunction(ctx, js_cell_number_min, "min", 2));
JS_SetPropertyStr(ctx, ctx->global_obj, "max",
JS_NewCFunction(ctx, js_cell_number_max, "max", 0));
JS_NewCFunction(ctx, js_cell_number_max, "max", 2));
JS_SetPropertyStr(ctx, ctx->global_obj, "remainder",
JS_NewCFunction(ctx, js_cell_number_remainder, "remainder", 2));
JS_SetPropertyStr(ctx, ctx->global_obj, "character",

View File

@@ -746,13 +746,32 @@ typedef enum JSCFunctionEnum {
JS_CFUNC_generic_magic,
JS_CFUNC_f_f,
JS_CFUNC_f_f_f,
/* Fixed-arity fast paths - no argc/argv overhead */
JS_CFUNC_0, /* JSValue f(ctx, this_val) */
JS_CFUNC_1, /* JSValue f(ctx, this_val, arg0) */
JS_CFUNC_2, /* JSValue f(ctx, this_val, arg0, arg1) */
JS_CFUNC_3, /* JSValue f(ctx, this_val, arg0, arg1, arg2) */
JS_CFUNC_4
} JSCFunctionEnum;
/* Fixed-arity C function types for fast paths */
typedef JSValue JSCFunction0(JSContext *ctx, JSValueConst this_val);
typedef JSValue JSCFunction1(JSContext *ctx, JSValueConst this_val, JSValueConst arg0);
typedef JSValue JSCFunction2(JSContext *ctx, JSValueConst this_val, JSValueConst arg0, JSValueConst arg1);
typedef JSValue JSCFunction3(JSContext *ctx, JSValueConst this_val, JSValueConst arg0, JSValueConst arg1, JSValueConst arg2);
typedef JSValue JSCFunction4(JSContext *ctx, JSValueConst this_val, JSValueConst arg0, JSValueConst arg1, JSValueConst arg2, JSValueConst arg3);
typedef union JSCFunctionType {
JSCFunction *generic;
JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
double (*f_f)(double);
double (*f_f_f)(double, double);
/* Fixed-arity fast paths */
JSCFunction0 *f0;
JSCFunction1 *f1;
JSCFunction2 *f2;
JSCFunction3 *f3;
JSCFunction4 *f4;
} JSCFunctionType;
JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
@@ -775,6 +794,32 @@ static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *fun
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
}
/* Fixed-arity fast path constructors */
static inline JSValue JS_NewCFuncFixed0(JSContext *ctx, JSCFunction0 *func, const char *name)
{
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, 0, JS_CFUNC_0, 0);
}
static inline JSValue JS_NewCFuncFixed1(JSContext *ctx, JSCFunction1 *func, const char *name)
{
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, 1, JS_CFUNC_1, 0);
}
static inline JSValue JS_NewCFuncFixed2(JSContext *ctx, JSCFunction2 *func, const char *name)
{
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, 2, JS_CFUNC_2, 0);
}
static inline JSValue JS_NewCFuncFixed3(JSContext *ctx, JSCFunction3 *func, const char *name)
{
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, 3, JS_CFUNC_3, 0);
}
static inline JSValue JS_NewCFuncFixed4(JSContext *ctx, JSCFunction4 *func, const char *name)
{
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, 4, JS_CFUNC_4, 0);
}
/* C property definition */
typedef struct JSCFunctionListEntry {
@@ -816,6 +861,11 @@ typedef struct JSCFunctionListEntry {
#define JS_CFUNC_DEF(name, length, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, 0, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } }
#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } }
/* Fixed-arity fast path macros */
#define JS_CFUNC0_DEF(name, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { 0, JS_CFUNC_0, { .f0 = func1 } } } }
#define JS_CFUNC1_DEF(name, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { 1, JS_CFUNC_1, { .f1 = func1 } } } }
#define JS_CFUNC2_DEF(name, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { 2, JS_CFUNC_2, { .f2 = func1 } } } }
#define JS_CFUNC3_DEF(name, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { 3, JS_CFUNC_3, { .f3 = func1 } } } }
#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, 0, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } }
#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } }
#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } }