Compare commits
2 Commits
f9170b33e5
...
8325253f1a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8325253f1a | ||
|
|
802c94085b |
49
build.cm
49
build.cm
@@ -121,11 +121,11 @@ Build.compile_file = function(pkg, file, target, buildtype = 'release') {
|
||||
|
||||
// Add buildtype-specific flags
|
||||
if (buildtype == 'release') {
|
||||
push(cmd_parts, '-O3', '-DNDEBUG')
|
||||
cmd_parts = array(cmd_parts, ['-O3', '-DNDEBUG'])
|
||||
} else if (buildtype == 'debug') {
|
||||
push(cmd_parts, '-O2', '-g')
|
||||
cmd_parts = array(cmd_parts, ['-O2', '-g'])
|
||||
} else if (buildtype == 'minsize') {
|
||||
push(cmd_parts, '-Os', '-DNDEBUG')
|
||||
cmd_parts = array(cmd_parts, ['-Os', '-DNDEBUG'])
|
||||
}
|
||||
|
||||
push(cmd_parts, '-DCELL_USE_NAME=' + sym_name)
|
||||
@@ -278,23 +278,20 @@ Build.build_dynamic = function(pkg, target = Build.detect_host_target(), buildty
|
||||
|
||||
// Platform-specific flags for undefined symbols (resolved at dlopen) and size optimization
|
||||
if (tc.system == 'darwin') {
|
||||
// Allow undefined symbols - they will be resolved when dlopen'd into the main executable
|
||||
push(cmd_parts, '-undefined', 'dynamic_lookup')
|
||||
// Dead-strip unused code
|
||||
push(cmd_parts, '-Wl,-dead_strip')
|
||||
// Set install_name to stable path so runtime finds it correctly
|
||||
push(cmd_parts, '-Wl,-install_name,' + stable_path)
|
||||
// rpath for .cell/local libraries
|
||||
push(cmd_parts, '-Wl,-rpath,@loader_path/../local')
|
||||
push(cmd_parts, '-Wl,-rpath,' + local_dir)
|
||||
cmd_parts = array(cmd_parts, [
|
||||
'-undefined', 'dynamic_lookup',
|
||||
'-Wl,-dead_strip',
|
||||
'-Wl,-install_name,' + stable_path,
|
||||
'-Wl,-rpath,@loader_path/../local',
|
||||
'-Wl,-rpath,' + local_dir
|
||||
])
|
||||
} else if (tc.system == 'linux') {
|
||||
// Allow undefined symbols at link time
|
||||
push(cmd_parts, '-Wl,--allow-shlib-undefined')
|
||||
// Garbage collect unused sections
|
||||
push(cmd_parts, '-Wl,--gc-sections')
|
||||
// rpath for .cell/local libraries
|
||||
push(cmd_parts, '-Wl,-rpath,$ORIGIN/../local')
|
||||
push(cmd_parts, '-Wl,-rpath,' + local_dir)
|
||||
cmd_parts = array(cmd_parts, [
|
||||
'-Wl,--allow-shlib-undefined',
|
||||
'-Wl,--gc-sections',
|
||||
'-Wl,-rpath,$ORIGIN/../local',
|
||||
'-Wl,-rpath,' + local_dir
|
||||
])
|
||||
} else if (tc.system == 'windows') {
|
||||
// Windows DLLs: use --allow-shlib-undefined for mingw
|
||||
push(cmd_parts, '-Wl,--allow-shlib-undefined')
|
||||
@@ -308,17 +305,11 @@ Build.build_dynamic = function(pkg, target = Build.detect_host_target(), buildty
|
||||
})
|
||||
|
||||
// Do NOT link against core library - symbols resolved at dlopen time
|
||||
cmd_parts = array(cmd_parts, resolved_ldflags)
|
||||
cmd_parts = array(cmd_parts, target_ldflags)
|
||||
|
||||
// Add LDFLAGS
|
||||
arrfor(resolved_ldflags, function(flag) {
|
||||
push(cmd_parts, flag)
|
||||
})
|
||||
|
||||
arrfor(target_ldflags, function(flag) {
|
||||
push(cmd_parts, flag)
|
||||
})
|
||||
|
||||
push(cmd_parts, '-o', '"' + store_path + '"')
|
||||
push(cmd_parts, '-o')
|
||||
push(cmd_parts, '"' + store_path + '"')
|
||||
|
||||
var cmd_str = text(cmd_parts, ' ')
|
||||
|
||||
|
||||
2
crypto.c
2
crypto.c
@@ -231,7 +231,7 @@ JSValue js_crypto_unlock(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
|
||||
static const JSCFunctionListEntry js_crypto_funcs[] = {
|
||||
JS_CFUNC_DEF("shared", 2, js_crypto_shared),
|
||||
JS_CFUNC_DEF("blake2", 1, js_crypto_blake2),
|
||||
JS_CFUNC_DEF("blake2", 2, js_crypto_blake2),
|
||||
JS_CFUNC_DEF("sign", 2, js_crypto_sign),
|
||||
JS_CFUNC_DEF("verify", 3, js_crypto_verify),
|
||||
JS_CFUNC_DEF("lock", 3, js_crypto_lock),
|
||||
|
||||
@@ -88,7 +88,7 @@ function use_core(path) {
|
||||
var script = text(script_blob)
|
||||
var mod = `(function setup_module(use){${script}})`
|
||||
var fn = js.eval('core:' + path, mod)
|
||||
var result = call(fn,sym, use_core)
|
||||
var result = call(fn,sym, [use_core])
|
||||
use_cache[cache_key] = result;
|
||||
return result;
|
||||
}
|
||||
@@ -185,7 +185,7 @@ function disrupt(err)
|
||||
|
||||
if (underlings) {
|
||||
var unders = array(underlings)
|
||||
arrfor(unders, function(id) {
|
||||
arrfor(unders, function(id, index) {
|
||||
log.console(`calling on ${id} to disrupt too`)
|
||||
$_.stop(create_actor({id}))
|
||||
})
|
||||
@@ -416,14 +416,14 @@ function handle_host(e) {
|
||||
peers[`${e.peer.address}:${e.peer.port}`] = e.peer
|
||||
var queue = peer_queue.get(e.peer)
|
||||
if (queue) {
|
||||
arrfor(queue, msg => e.peer.send(nota.encode(msg)))
|
||||
arrfor(queue, (msg, index) => e.peer.send(nota.encode(msg)))
|
||||
log.system(`sent ${msg} out of queue`)
|
||||
peer_queue.delete(e.peer)
|
||||
}
|
||||
break
|
||||
case "disconnect":
|
||||
peer_queue.delete(e.peer)
|
||||
arrfor(array(peers), function(id) {
|
||||
arrfor(array(peers), function(id, index) {
|
||||
if (peers[id] == e.peer) delete peers[id]
|
||||
})
|
||||
log.system('portal got disconnect from ' + e.peer.address + ":" + e.peer.port)
|
||||
@@ -440,7 +440,7 @@ function handle_host(e) {
|
||||
obj[ACTORDATA].address = e.peer.address
|
||||
obj[ACTORDATA].port = e.peer.port
|
||||
}
|
||||
arrfor(array(obj), function(key) {
|
||||
arrfor(array(obj), function(key, index) {
|
||||
if (key in obj)
|
||||
populate_actor_addresses(obj[key])
|
||||
})
|
||||
@@ -496,11 +496,6 @@ $_.unneeded = function unneeded(fn, seconds) {
|
||||
|
||||
// schedules the invocation of a function after a specified amount of time.
|
||||
$_.delay = function delay(fn, seconds = 0) {
|
||||
if (seconds <= 0) {
|
||||
$_.clock(fn)
|
||||
return
|
||||
}
|
||||
|
||||
function delay_turn() {
|
||||
fn()
|
||||
send_messages()
|
||||
@@ -592,7 +587,7 @@ var need_stop = false
|
||||
return
|
||||
}
|
||||
|
||||
arrfor(message_queue, function(msg) {
|
||||
arrfor(message_queue, function(msg, index) {
|
||||
if (msg.startup) {
|
||||
// now is the time to actually spin up the actor
|
||||
actor_mod.createactor(msg.startup)
|
||||
@@ -817,7 +812,7 @@ $_.clock(_ => {
|
||||
|
||||
// Call with signature: setup_module(args, use, env)
|
||||
// The script wrapper binds $delay, $start, etc. from env
|
||||
var val = call(locator.symbol, null, _cell.args.arg, use_fn, env)
|
||||
var val = call(locator.symbol, null, [_cell.args.arg, use_fn, env])
|
||||
|
||||
if (val)
|
||||
throw Error('Program must not return anything');
|
||||
|
||||
@@ -561,7 +561,7 @@ Shop.open_package_dylib = function(pkg) {
|
||||
var content = text(fd.slurp(toml_path))
|
||||
var cfg = toml.decode(content)
|
||||
if (cfg.dependencies) {
|
||||
arrfor(array(cfg.dependencies), function(alias) {
|
||||
arrfor(array(cfg.dependencies), function(alias, i) {
|
||||
var dep_pkg = cfg.dependencies[alias]
|
||||
try {
|
||||
Shop.open_package_dylib(dep_pkg)
|
||||
@@ -812,7 +812,7 @@ function execute_module(info)
|
||||
|
||||
// Call with signature: setup_module(args, use, env)
|
||||
// args is null for module loading
|
||||
used = call(mod_resolve.symbol, context, null, use_fn, env)
|
||||
used = call(mod_resolve.symbol, context, [null, use_fn, env])
|
||||
} else if (c_resolve.scope < 900) {
|
||||
// C only
|
||||
used = call_c_module(c_resolve)
|
||||
@@ -1195,11 +1195,11 @@ Shop.module_reload = function(path, package) {
|
||||
var old = use_cache[cache_key]
|
||||
var newmod = get_module(path, package)
|
||||
|
||||
arrfor(array(newmod), function(i) {
|
||||
arrfor(array(newmod), function(i, idx) {
|
||||
old[i] = newmod[i]
|
||||
})
|
||||
|
||||
arrfor(array(old), function(i) {
|
||||
arrfor(array(old), function(i, idx) {
|
||||
if (!(i in newmod))
|
||||
old[i] = null
|
||||
})
|
||||
@@ -1226,7 +1226,7 @@ Shop.build_package_scripts = function(package)
|
||||
var scripts = get_package_scripts(package)
|
||||
var pkg_dir = get_package_abs_dir(package)
|
||||
|
||||
arrfor(scripts, function(script) {
|
||||
arrfor(scripts, function(script, i) {
|
||||
resolve_mod_fn(pkg_dir + '/' + script, package)
|
||||
})
|
||||
}
|
||||
@@ -1284,7 +1284,7 @@ Shop.audit_packages = function() {
|
||||
|
||||
var bad = []
|
||||
|
||||
arrfor(packages, function(package) {
|
||||
arrfor(packages, function(package, i) {
|
||||
if (package == 'core') return
|
||||
if (fd.is_dir(package)) return
|
||||
if (fetch_remote_hash(package)) return
|
||||
|
||||
@@ -300,8 +300,6 @@ DEF( set_var_ref1, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
||||
|
||||
DEF( get_length, 1, 1, 1, none)
|
||||
|
||||
DEF( if_false8, 2, 1, 0, label8)
|
||||
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
||||
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
|
||||
|
||||
431
source/quickjs.c
431
source/quickjs.c
@@ -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 {
|
||||
@@ -994,10 +994,10 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);
|
||||
static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
|
||||
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValueConst *argv, int flags);
|
||||
int argc, JSValueConst *argv);
|
||||
static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValueConst *argv, int flags);
|
||||
int argc, JSValueConst *argv);
|
||||
static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValue *argv, int flags);
|
||||
@@ -1035,7 +1035,7 @@ static void gc_decref_child_dbg(JSRuntime *rt, JSGCObjectHeader *parent,
|
||||
#endif
|
||||
|
||||
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
||||
|
||||
static blob *js_get_blob(JSContext *ctx, JSValueConst val);
|
||||
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
|
||||
static int JS_ToBoolFree(JSContext *ctx, JSValue val);
|
||||
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
|
||||
@@ -1106,7 +1106,7 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
|
||||
JSValue **arrpp, uint32_t *countp);
|
||||
static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_val,
|
||||
int argc, JSValueConst *argv, int flags);
|
||||
int argc, JSValueConst *argv);
|
||||
static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);
|
||||
static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
|
||||
JSGCObjectTypeEnum type);
|
||||
@@ -4891,13 +4891,6 @@ JSValue JS_NewObject(JSContext *ctx)
|
||||
return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT);
|
||||
}
|
||||
|
||||
static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj,
|
||||
JSAtom name, int len)
|
||||
{
|
||||
JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len));
|
||||
JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_name, JS_AtomToString(ctx, name));
|
||||
}
|
||||
|
||||
/* Helper to check if a value is a bytecode function */
|
||||
static BOOL js_is_bytecode_function(JSValueConst val)
|
||||
{
|
||||
@@ -4993,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];
|
||||
@@ -5001,15 +4994,13 @@ typedef struct JSCFunctionDataRecord {
|
||||
|
||||
static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_val,
|
||||
int argc, JSValueConst *argv, int flags)
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
JSCFunctionDataRecord *s = f->u.c_function_data_record;
|
||||
JSValueConst *arg_buf;
|
||||
int i;
|
||||
|
||||
(void)flags; /* unused */
|
||||
|
||||
/* XXX: could add the function on the stack for debug */
|
||||
if (unlikely(argc < s->length)) {
|
||||
arg_buf = alloca(sizeof(arg_buf[0]) * s->length);
|
||||
@@ -9095,29 +9086,6 @@ static void js_print_atom(JSPrintValueState *s, JSAtom atom)
|
||||
}
|
||||
}
|
||||
|
||||
/* return 0 if invalid length */
|
||||
static uint32_t js_print_array_get_length(JSObject *p)
|
||||
{
|
||||
JSProperty *pr;
|
||||
JSShapeProperty *prs;
|
||||
JSValueConst val;
|
||||
|
||||
prs = find_own_property(&pr, p, JS_ATOM_length);
|
||||
if (!prs)
|
||||
return 0;
|
||||
if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)
|
||||
return 0;
|
||||
val = pr->u.value;
|
||||
switch(JS_VALUE_GET_NORM_TAG(val)) {
|
||||
case JS_TAG_INT:
|
||||
return JS_VALUE_GET_INT(val);
|
||||
case JS_TAG_FLOAT64:
|
||||
return (uint32_t)JS_VALUE_GET_FLOAT64(val);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void js_print_comma(JSPrintValueState *s, int *pcomma_state)
|
||||
{
|
||||
switch(*pcomma_state) {
|
||||
@@ -10165,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 */
|
||||
@@ -10213,7 +10181,7 @@ static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int var_idx)
|
||||
|
||||
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValueConst *argv, int flags)
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
JSRuntime *rt = ctx->rt;
|
||||
JSCFunctionType func;
|
||||
@@ -10224,7 +10192,6 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
int arg_count, i;
|
||||
JSCFunctionEnum cproto;
|
||||
|
||||
(void)flags; /* unused */
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
cproto = f->u.cfunc.cproto;
|
||||
arg_count = f->length;
|
||||
@@ -10296,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();
|
||||
}
|
||||
@@ -10314,7 +10294,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
|
||||
static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValueConst *argv, int flags)
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
JSFunction *f;
|
||||
JSBoundFunction *bf;
|
||||
@@ -10322,7 +10302,6 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
||||
int arg_count, i;
|
||||
|
||||
(void)this_obj; /* unused - bound function uses bf->this_val */
|
||||
(void)flags; /* unused */
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
bf = f->u.bound_function;
|
||||
arg_count = bf->argc + argc;
|
||||
@@ -10470,16 +10449,21 @@ 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, flags);
|
||||
(JSValueConst *)argv);
|
||||
case JS_FUNC_KIND_BOUND:
|
||||
return js_call_bound_function(caller_ctx, func_obj, this_obj, argc,
|
||||
(JSValueConst *)argv, flags);
|
||||
(JSValueConst *)argv);
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
return js_c_function_data_call(caller_ctx, func_obj, this_obj, argc,
|
||||
(JSValueConst *)argv, flags);
|
||||
(JSValueConst *)argv);
|
||||
case JS_FUNC_KIND_BYTECODE:
|
||||
break; /* continue to bytecode execution below */
|
||||
default:
|
||||
@@ -10594,24 +10578,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
CASE(OP_push_empty_string):
|
||||
*sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string);
|
||||
BREAK;
|
||||
CASE(OP_get_length):
|
||||
{
|
||||
JSValue val;
|
||||
|
||||
/* Functions don't support property access in cell script */
|
||||
if (js_is_proxy_callable(sp[-1])) {
|
||||
JS_ThrowTypeError(ctx, "cannot get property of function");
|
||||
goto exception;
|
||||
}
|
||||
|
||||
sf->cur_pc = pc;
|
||||
val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length);
|
||||
if (unlikely(JS_IsException(val)))
|
||||
goto exception;
|
||||
JS_FreeValue(ctx, sp[-1]);
|
||||
sp[-1] = val;
|
||||
}
|
||||
BREAK;
|
||||
#endif
|
||||
CASE(OP_push_atom_value):
|
||||
*sp++ = JS_AtomToValue(ctx, get_u32(pc));
|
||||
@@ -11037,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;
|
||||
@@ -15844,64 +15820,34 @@ static __exception int js_parse_left_hand_side_expr(JSParseState *s)
|
||||
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
|
||||
}
|
||||
|
||||
#define ARRAY_LITERAL_MAX 1024
|
||||
|
||||
static __exception int js_parse_array_literal(JSParseState *s)
|
||||
{
|
||||
uint32_t idx;
|
||||
BOOL need_length;
|
||||
uint32_t idx = 0;
|
||||
|
||||
if (next_token(s))
|
||||
return -1;
|
||||
/* small regular arrays are created on the stack */
|
||||
idx = 0;
|
||||
while (s->token.val != ']' && idx < 32) {
|
||||
if (s->token.val == ',')
|
||||
break;
|
||||
if (js_parse_assign_expr(s))
|
||||
return -1;
|
||||
idx++;
|
||||
/* accept trailing comma */
|
||||
if (s->token.val == ',') {
|
||||
if (next_token(s))
|
||||
return -1;
|
||||
} else
|
||||
if (s->token.val != ']')
|
||||
goto done;
|
||||
}
|
||||
emit_op(s, OP_array_from);
|
||||
emit_u16(s, idx);
|
||||
if (next_token(s)) return -1;
|
||||
|
||||
/* larger arrays and holes are handled with explicit indices */
|
||||
need_length = FALSE;
|
||||
while (s->token.val != ']' && idx < 0x7fffffff) {
|
||||
need_length = TRUE;
|
||||
if (s->token.val != ',') {
|
||||
JSAtom atom;
|
||||
if (js_parse_assign_expr(s))
|
||||
return -1;
|
||||
atom = JS_NewAtomUInt32(s->ctx, idx);
|
||||
emit_op(s, OP_define_field);
|
||||
emit_atom(s, atom);
|
||||
JS_FreeAtom(s->ctx, atom);
|
||||
need_length = FALSE;
|
||||
}
|
||||
idx++;
|
||||
/* accept trailing comma */
|
||||
if (s->token.val == ',') {
|
||||
if (next_token(s))
|
||||
return -1;
|
||||
}
|
||||
while (s->token.val != ']' && idx < ARRAY_LITERAL_MAX) {
|
||||
if (s->token.val == ',')
|
||||
return js_parse_error(s, "array holes not allowed");
|
||||
|
||||
if (js_parse_assign_expr(s)) return -1;
|
||||
idx++;
|
||||
|
||||
if (s->token.val == ',') {
|
||||
if (next_token(s)) return -1;
|
||||
} else if (s->token.val != ']') {
|
||||
return js_parse_error(s, "expected ',' or ']'");
|
||||
}
|
||||
if (need_length) {
|
||||
/* Set the length: Cannot use OP_define_field because
|
||||
length is not configurable */
|
||||
emit_op(s, OP_dup);
|
||||
emit_op(s, OP_push_i32);
|
||||
emit_u32(s, idx);
|
||||
emit_op(s, OP_put_field);
|
||||
emit_atom(s, JS_ATOM_length);
|
||||
}
|
||||
done:
|
||||
return js_parse_expect(s, ']');
|
||||
}
|
||||
|
||||
if (s->token.val != ']')
|
||||
return js_parse_error(s, "array literal too long");
|
||||
|
||||
emit_op(s, OP_array_from);
|
||||
emit_u16(s, idx);
|
||||
return js_parse_expect(s, ']');
|
||||
}
|
||||
|
||||
/* XXX: remove */
|
||||
@@ -21167,18 +21113,6 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
|
||||
}
|
||||
}
|
||||
goto no_change;
|
||||
|
||||
case OP_get_field:
|
||||
if (OPTIMIZE) {
|
||||
JSAtom atom = get_u32(bc_buf + pos + 1);
|
||||
if (atom == JS_ATOM_length) {
|
||||
JS_FreeAtom(ctx, atom);
|
||||
add_pc2line_info(s, bc_out.size, line_num);
|
||||
dbuf_putc(&bc_out, OP_get_length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto no_change;
|
||||
#endif
|
||||
case OP_push_atom_value:
|
||||
if (OPTIMIZE) {
|
||||
@@ -22164,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 &&
|
||||
@@ -22248,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) {
|
||||
@@ -22258,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;
|
||||
@@ -22293,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);
|
||||
@@ -22318,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;
|
||||
@@ -22342,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);
|
||||
@@ -22370,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;
|
||||
@@ -23262,49 +23187,6 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int JS_WriteArray(BCWriterState *s, JSValueConst obj)
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(obj);
|
||||
uint32_t i, len;
|
||||
JSValue val;
|
||||
int ret;
|
||||
BOOL is_template;
|
||||
|
||||
if (s->allow_bytecode && p->stone) {
|
||||
/* not extensible array: we consider it is a
|
||||
template when we are saving bytecode */
|
||||
bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT);
|
||||
is_template = TRUE;
|
||||
} else {
|
||||
bc_put_u8(s, BC_TAG_ARRAY);
|
||||
is_template = FALSE;
|
||||
}
|
||||
if (js_get_length32(s->ctx, &len, obj))
|
||||
goto fail1;
|
||||
bc_put_leb128(s, len);
|
||||
for(i = 0; i < len; i++) {
|
||||
val = JS_GetPropertyUint32(s->ctx, obj, i);
|
||||
if (JS_IsException(val))
|
||||
goto fail1;
|
||||
ret = JS_WriteObjectRec(s, val);
|
||||
JS_FreeValue(s->ctx, val);
|
||||
if (ret)
|
||||
goto fail1;
|
||||
}
|
||||
if (is_template) {
|
||||
val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw);
|
||||
if (JS_IsException(val))
|
||||
goto fail1;
|
||||
ret = JS_WriteObjectRec(s, val);
|
||||
JS_FreeValue(s->ctx, val);
|
||||
if (ret)
|
||||
goto fail1;
|
||||
}
|
||||
return 0;
|
||||
fail1:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(obj);
|
||||
@@ -24549,12 +24431,33 @@ static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val,
|
||||
static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
|
||||
JSValueConst obj)
|
||||
{
|
||||
int tag = JS_VALUE_GET_TAG(obj);
|
||||
|
||||
/* Fast path for intrinsic arrays */
|
||||
if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) {
|
||||
if (tag == JS_TAG_ARRAY) {
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY(obj);
|
||||
*pres = arr->len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag == JS_TAG_FUNCTION) {
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(obj);
|
||||
*pres = fn->length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
blob *b = js_get_blob(ctx, obj);
|
||||
if (b) {
|
||||
*pres = b->length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE) {
|
||||
JSString *p = JS_VALUE_GET_STRING(obj);
|
||||
*pres = p->len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
JSValue len_val;
|
||||
len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);
|
||||
if (JS_IsException(len_val)) {
|
||||
@@ -24634,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;
|
||||
@@ -27988,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;
|
||||
|
||||
@@ -28002,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;
|
||||
@@ -28024,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;
|
||||
@@ -28476,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;
|
||||
@@ -28494,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;
|
||||
@@ -28559,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);
|
||||
@@ -28578,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);
|
||||
@@ -28611,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);
|
||||
@@ -28618,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);
|
||||
@@ -28964,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)
|
||||
{
|
||||
@@ -28987,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;
|
||||
|
||||
@@ -29337,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;
|
||||
}
|
||||
|
||||
@@ -29525,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),
|
||||
|
||||
@@ -30038,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)
|
||||
{
|
||||
@@ -30053,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;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
@@ -30315,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);
|
||||
@@ -30383,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",
|
||||
@@ -30395,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",
|
||||
@@ -30425,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",
|
||||
|
||||
@@ -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 } }
|
||||
|
||||
Reference in New Issue
Block a user