Page MenuHomePhorge

calls.h
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None
#ifndef SV_CALLS_H
#define SV_CALLS_H
#include <limits.h>
#include "silver/engine.h"
typedef struct {
ant_value_t *args;
int argc;
ant_value_t *alloc;
} sv_call_args_t;
static inline void sv_call_args_reset(sv_call_args_t *a, ant_value_t *args, int argc) {
a->args = args;
a->argc = argc;
a->alloc = NULL;
}
static inline void sv_call_args_release(sv_call_args_t *a) {
if (a->alloc) free(a->alloc);
a->alloc = NULL;
}
static inline ant_value_t sv_apply_normalize_args(ant_t *js, sv_call_args_t *a) {
if (a->argc != 1) return js_mkundef();
ant_value_t arg_array = a->args[0];
uint8_t t = vtype(arg_array);
if (t == T_UNDEF || t == T_NULL) {
a->args = NULL;
a->argc = 0;
return js_mkundef();
}
if (t != T_ARR) {
return js_mkerr_typed(js, JS_ERR_TYPE,
"apply arguments must be an array or null/undefined");
}
ant_offset_t len = js_arr_len(js, arg_array);
if (len <= 0) {
a->args = NULL;
a->argc = 0;
return js_mkundef();
}
if (len > INT_MAX)
return js_mkerr(js, "too many arguments");
a->alloc = malloc((size_t)len * sizeof(ant_value_t));
if (!a->alloc) return js_mkerr(js, "out of memory");
for (ant_offset_t i = 0; i < len; i++)
a->alloc[i] = js_arr_get(js, arg_array, i);
a->args = a->alloc;
a->argc = (int)len;
return js_mkundef();
}
static inline ant_value_t sv_op_new(sv_vm_t *vm, ant_t *js, uint8_t *ip) {
uint16_t argc = sv_get_u16(ip + 1);
ant_value_t *args = &vm->stack[vm->sp - argc];
ant_value_t new_target = vm->stack[vm->sp - argc - 1];
ant_value_t func = vm->stack[vm->sp - argc - 2];
ant_value_t record_func = func;
js->new_target = new_target;
if (vtype(func) == T_OBJ && is_proxy(func)) {
ant_value_t result = js_proxy_construct(js, func, args, argc, new_target);
vm->sp -= argc + 2;
if (is_err(result)) return result;
vm->stack[vm->sp++] = result;
return result;
}
if (!js_is_constructor(func)) {
vm->sp -= argc + 2;
return js_mkerr_typed(js, JS_ERR_TYPE, "not a constructor");
}
ant_value_t proto = js_mkundef();
if (vtype(func) == T_FUNC) {
ant_value_t proto_source = func;
ant_value_t func_obj = js_func_obj(func);
ant_value_t target_func = js_get_slot(func_obj, SLOT_TARGET_FUNC);
if (vtype(target_func) == T_FUNC) {
proto_source = target_func;
record_func = target_func;
}
proto = js_getprop_fallback(js, proto_source, "prototype");
}
ant_value_t obj = js_mkobj_with_inobj_limit(js, sv_tfb_ctor_inobj_limit(record_func));
if (is_object_type(proto)) js_set_proto_init(obj, proto);
ant_value_t ctor_this = obj;
ant_value_t result = sv_vm_call(vm, js, func, obj, args, argc, &ctor_this, true);
vm->sp -= argc + 2;
if (is_err(result)) return result;
ant_value_t final_obj =
is_object_type(result) ? result
: (is_object_type(ctor_this) ? ctor_this : obj);
sv_tfb_record_ctor_prop_count(record_func, final_obj);
vm->stack[vm->sp++] = final_obj;
return result;
}
static inline ant_value_t sv_op_apply(sv_vm_t *vm, ant_t *js, uint8_t *ip) {
uint16_t argc = sv_get_u16(ip + 1);
ant_value_t *args = &vm->stack[vm->sp - argc];
ant_value_t this = vm->stack[vm->sp - argc - 1];
ant_value_t func = vm->stack[vm->sp - argc - 2];
sv_call_args_t call;
sv_call_args_reset(&call, args, (int)argc);
ant_value_t norm = sv_apply_normalize_args(js, &call);
if (is_err(norm)) return norm;
ant_value_t result = sv_vm_call(vm, js, func, this, call.args, call.argc, NULL, false);
sv_call_args_release(&call);
vm->sp -= argc + 2;
if (!is_err(result)) vm->stack[vm->sp++] = result;
return result;
}
static inline ant_value_t sv_op_super_apply(sv_vm_t *vm, ant_t *js, sv_frame_t *frame, uint8_t *ip) {
uint16_t argc = sv_get_u16(ip + 1);
ant_value_t *args = &vm->stack[vm->sp - argc];
ant_value_t this = vm->stack[vm->sp - argc - 1];
ant_value_t func = vm->stack[vm->sp - argc - 2];
sv_call_args_t call;
sv_call_args_reset(&call, args, (int)argc);
ant_value_t norm = sv_apply_normalize_args(js, &call);
if (is_err(norm)) return norm;
if (frame) js->new_target = frame->new_target;
ant_value_t super_this = this;
ant_value_t result = sv_vm_call(
vm, js, func, this, call.args, call.argc, &super_this, true);
sv_call_args_release(&call);
vm->sp -= argc + 2;
if (frame && !is_err(result))
frame->this = is_object_type(result) ? result : super_this;
if (!is_err(result)) vm->stack[vm->sp++] = result;
return result;
}
static inline ant_value_t sv_op_new_apply(sv_vm_t *vm, ant_t *js, uint8_t *ip) {
uint16_t argc = sv_get_u16(ip + 1);
ant_value_t *args = &vm->stack[vm->sp - argc];
ant_value_t new_target = vm->stack[vm->sp - argc - 1];
ant_value_t func = vm->stack[vm->sp - argc - 2];
ant_value_t record_func = func;
js->new_target = new_target;
sv_call_args_t call;
sv_call_args_reset(&call, args, (int)argc);
ant_value_t norm = sv_apply_normalize_args(js, &call);
if (is_err(norm)) { vm->sp -= argc + 2; return norm; }
if (vtype(func) == T_OBJ && is_proxy(func)) {
ant_value_t result = js_proxy_construct(js, func, call.args, call.argc, new_target);
sv_call_args_release(&call);
vm->sp -= argc + 2;
if (is_err(result)) return result;
vm->stack[vm->sp++] = result;
return result;
}
if (!js_is_constructor(func)) {
sv_call_args_release(&call);
vm->sp -= argc + 2;
return js_mkerr_typed(js, JS_ERR_TYPE, "not a constructor");
}
ant_value_t proto = js_mkundef();
if (vtype(func) == T_FUNC) {
ant_value_t proto_source = func;
ant_value_t func_obj = js_func_obj(func);
ant_value_t target_func = js_get_slot(func_obj, SLOT_TARGET_FUNC);
if (vtype(target_func) == T_FUNC) {
proto_source = target_func;
record_func = target_func;
}
proto = js_getprop_fallback(js, proto_source, "prototype");
}
ant_value_t obj = js_mkobj_with_inobj_limit(js, sv_tfb_ctor_inobj_limit(record_func));
if (is_object_type(proto)) js_set_proto_init(obj, proto);
ant_value_t ctor_this = obj;
ant_value_t result = sv_vm_call(vm, js, func, obj, call.args, call.argc, &ctor_this, true);
sv_call_args_release(&call);
vm->sp -= argc + 2;
if (is_err(result)) return result;
ant_value_t final_obj =
is_object_type(result) ? result
: (is_object_type(ctor_this) ? ctor_this : obj);
sv_tfb_record_ctor_prop_count(record_func, final_obj);
vm->stack[vm->sp++] = final_obj;
return result;
}
static inline ant_value_t sv_op_eval(sv_vm_t *vm, ant_t *js, sv_frame_t *frame, uint8_t *ip) {
ant_value_t code = vm->stack[--vm->sp];
if (vtype(code) != T_STR) {
vm->stack[vm->sp++] = code;
return code;
}
ant_offset_t len;
ant_offset_t off = vstr(js, code, &len);
const char *str = (const char *)(uintptr_t)(off);
ant_value_t result = js_eval_bytecode_eval_with_strict(
js, str, len, sv_frame_is_strict(frame));
if (!is_err(result)) vm->stack[vm->sp++] = result;
return result;
}
static inline ant_value_t sv_op_check_ctor(sv_vm_t *vm, ant_t *js) {
if (vtype(sv_vm_get_new_target(vm, js)) == T_UNDEF)
return js_mkerr_typed(js, JS_ERR_TYPE,
"Class constructor cannot be invoked without 'new'");
return tov(0);
}
static inline void sv_op_check_ctor_ret(sv_vm_t *vm, sv_frame_t *frame) {
ant_value_t val = vm->stack[vm->sp - 1];
if (is_object_type(val)) {
vm->stack[vm->sp++] = val;
} else vm->stack[vm->sp++] = frame->this;
}
#endif

File Metadata

Mime Type
text/x-c
Expires
Sat, May 2, 9:02 PM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
541443
Default Alt Text
calls.h (7 KB)

Event Timeline