Page MenuHomePhorge

coercion.h
No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None

coercion.h

#ifndef SV_COERCION_H
#define SV_COERCION_H
#include "silver/engine.h"
#include "esm/loader.h"
#include <string.h>
#include "globals.h"
#include "property.h"
static inline ant_value_t sv_module_export_cstr(
ant_t *js,
const char *name, size_t len,
ant_value_t value
) {
ant_value_t module_ns = js_module_eval_active_ns(js);
if (vtype(module_ns) != T_OBJ)
return js_mkerr_typed(js, JS_ERR_SYNTAX, "export used outside module");
ant_value_t set_res = setprop_cstr(js, module_ns, name, len, value);
if (is_err(set_res)) return set_res;
if (len == 7 && memcmp(name, "default", 7) == 0)
js_set_slot_wb(js, module_ns, SLOT_DEFAULT, value);
return tov(0);
}
static inline ant_value_t sv_op_to_object(sv_vm_t *vm, ant_t *js) {
ant_value_t v = vm->stack[vm->sp - 1];
uint8_t t = vtype(v);
if (t == T_OBJ || t == T_ARR || t == T_FUNC) return tov(0);
if (t == T_NULL || t == T_UNDEF)
return js_mkerr_typed(js, JS_ERR_TYPE,
"Cannot convert undefined or null to object");
ant_value_t obj = mkobj(js, 0);
ant_value_t obj_as_obj = js_as_obj(obj);
js_set_slot(obj_as_obj, SLOT_PRIMITIVE, v);
vm->stack[vm->sp - 1] = obj;
return tov(0);
}
static inline void sv_op_to_propkey(sv_vm_t *vm, ant_t *js) {
ant_value_t v = vm->stack[vm->sp - 1];
if (vtype(v) != T_STR && vtype(v) != T_SYMBOL)
vm->stack[vm->sp - 1] = coerce_to_str(js, v);
}
static inline void sv_op_is_undef(sv_vm_t *vm) {
ant_value_t v = vm->stack[vm->sp - 1];
vm->stack[vm->sp - 1] = mkval(T_BOOL, vtype(v) == T_UNDEF);
}
static inline void sv_op_is_null(sv_vm_t *vm) {
ant_value_t v = vm->stack[vm->sp - 1];
vm->stack[vm->sp - 1] = mkval(T_BOOL, vtype(v) == T_NULL);
}
static inline ant_value_t sv_op_import(sv_vm_t *vm, ant_t *js) {
ant_value_t specifier = vm->stack[--vm->sp];
ant_value_t import_fn = js_get_module_import_binding(js);
if (vtype(import_fn) != T_FUNC && vtype(import_fn) != T_CFUNC)
import_fn = js_getprop_fallback(js, js->global, "import");
if (vtype(import_fn) == T_FUNC || vtype(import_fn) == T_CFUNC) {
ant_value_t result = sv_vm_call(vm, js, import_fn, js->global, &specifier, 1, NULL, false);
if (!is_err(result)) vm->stack[vm->sp++] = result;
return result;
}
vm->stack[vm->sp++] = mkval(T_UNDEF, 0);
return tov(0);
}
static inline ant_value_t sv_op_import_sync(sv_vm_t *vm, ant_t *js) {
ant_value_t specifier = vm->stack[--vm->sp];
ant_value_t result = js_esm_import_sync(js, specifier);
if (!is_err(result)) vm->stack[vm->sp++] = result;
return result;
}
static inline void sv_op_import_default(sv_vm_t *vm, ant_t *js) {
ant_value_t ns = vm->stack[vm->sp - 1];
if (vtype(ns) == T_OBJ) {
ant_value_t slot_val = js_get_slot(ns, SLOT_DEFAULT);
if (vtype(slot_val) != T_UNDEF) { vm->stack[vm->sp - 1] = slot_val; return; }
}
}
static inline bool sv_module_namespace_has_export(
ant_t *js,
ant_value_t ns,
const char *name,
size_t len
) {
if (!is_object_type(ns)) return false;
ant_value_t as_obj = js_as_obj(ns);
if (is_proxy(as_obj)) return false;
if (lkp(js, as_obj, name, len) != 0) return true;
prop_meta_t meta;
return lookup_string_prop_meta(js, as_obj, name, len, &meta);
}
static inline const char *sv_module_namespace_display_name(ant_t *js, ant_value_t ns) {
if (!is_object_type(ns)) return NULL;
ant_value_t module_ctx = js_get_slot(ns, SLOT_MODULE_CTX);
if (!is_object_type(module_ctx)) return NULL;
ant_value_t display_name = js_get(js, module_ctx, "displayName");
if (vtype(display_name) == T_STR) return js_getstr(js, display_name, NULL);
ant_value_t filename = js_get(js, module_ctx, "filename");
if (vtype(filename) != T_STR) return NULL;
return js_getstr(js, filename, NULL);
}
static inline ant_value_t sv_missing_named_export_error(
ant_t *js,
ant_value_t ns,
const char *name,
size_t len
) {
const char *display_name = sv_module_namespace_display_name(js, ns);
if (!display_name) display_name = "<unknown>";
return js_mkerr_typed(
js, JS_ERR_SYNTAX,
"The requested module '%s' does not provide an export named '%.*s'",
display_name, (int)len, name
);
}
static inline ant_value_t sv_op_import_named(
sv_vm_t *vm,
ant_t *js,
sv_func_t *func,
uint8_t *ip
) {
uint32_t atom_idx = sv_get_u32(ip + 1);
if (atom_idx >= (uint32_t)func->atom_count)
return js_mkerr(js, "invalid import atom index");
ant_value_t ns = vm->stack[vm->sp - 1];
sv_atom_t *a = &func->atoms[atom_idx];
if (
!sv_module_namespace_has_export(js, ns, a->str, a->len) &&
js_get_slot(ns, SLOT_MODULE_LOADING) != js_true
) return sv_missing_named_export_error(js, ns, a->str, a->len);
ant_value_t value = js_get(js, ns, a->str);
if (is_err(value)) return value;
vm->stack[vm->sp - 1] = value;
return tov(0);
}
static inline ant_value_t sv_op_export(sv_vm_t *vm, ant_t *js, sv_func_t *func, uint8_t *ip) {
uint32_t atom_idx = sv_get_u32(ip + 1);
if (atom_idx >= (uint32_t)func->atom_count)
return js_mkerr(js, "invalid export atom index");
ant_value_t value = vm->stack[--vm->sp];
sv_atom_t *a = &func->atoms[atom_idx];
return sv_module_export_cstr(js, a->str, a->len, value);
}
static inline ant_value_t sv_op_export_all(sv_vm_t *vm, ant_t *js) {
ant_value_t ns = vm->stack[--vm->sp];
if (vtype(ns) != T_OBJ)
return js_mkerr_typed(js, JS_ERR_SYNTAX, "Cannot re-export from non-object module");
ant_iter_t iter = js_prop_iter_begin(js, ns);
const char *key = NULL;
size_t key_len = 0;
ant_value_t value = js_mkundef();
while (js_prop_iter_next(&iter, &key, &key_len, &value)) {
ant_value_t export_res = sv_module_export_cstr(js, key, key_len, value);
if (is_err(export_res)) { js_prop_iter_end(&iter); return export_res; }
}
js_prop_iter_end(&iter);
return tov(0);
}
static inline ant_value_t sv_op_enter_with(sv_vm_t *vm, ant_t *js, sv_frame_t *frame) {
if (sv_frame_is_strict(frame))
return js_mkerr_typed(js, JS_ERR_SYNTAX, "with statement not allowed in strict mode");
frame->with_obj = vm->stack[--vm->sp];
return js_mkundef();
}
static inline void sv_op_exit_with(sv_vm_t *vm, sv_frame_t *frame) {
frame->with_obj = js_mkundef();
}
enum {
WITH_FB_GLOBAL = 0,
WITH_FB_LOCAL = 1,
WITH_FB_ARG = 2,
WITH_FB_UPVAL = 3
};
static inline ant_value_t sv_with_fallback_get(
sv_vm_t *vm, ant_t *js,
sv_frame_t *frame,
uint8_t kind, uint16_t idx
) {
switch (kind) {
case WITH_FB_LOCAL: return frame->lp ? frame->lp[idx] : js_mkundef();
case WITH_FB_ARG: return sv_frame_get_arg_value(frame, idx);
case WITH_FB_UPVAL: {
if (!frame->upvalues || (int)idx >= frame->upvalue_count) return js_mkundef();
sv_upvalue_t *uv = frame->upvalues[idx];
return uv ? *uv->location : js_mkundef();
}
default: return sv_global_get(js, NULL, 0);
}}
static inline void sv_with_fallback_put(
sv_vm_t *vm, ant_t *js,
sv_frame_t *frame,
uint8_t kind, uint16_t idx,
ant_value_t val
) {
switch (kind) {
case WITH_FB_LOCAL:
if (frame->lp) frame->lp[idx] = val;
break;
case WITH_FB_ARG:
sv_frame_set_arg_value(js, frame, idx, val);
break;
case WITH_FB_UPVAL:
if (frame->upvalues && (int)idx < frame->upvalue_count) {
sv_upvalue_t *uv = frame->upvalues[idx];
if (uv) *uv->location = val;
}
break;
default: break;
}
}
static inline bool sv_try_get_with_bound_value(
ant_t *js,
ant_value_t with_obj,
const sv_atom_t *a,
ant_value_t *out
) {
ant_object_t *ptr = is_object_type(with_obj) ? js_obj_ptr(js_as_obj(with_obj)) : NULL;
const char *interned = intern_string(a->str, a->len);
if (ptr && interned) {
bool should_fallback = false;
if (sv_try_get_shape_data_prop(js, ptr, interned, out, &should_fallback)) return true;
if (!should_fallback) return false;
}
if (lkp(js, with_obj, a->str, a->len) == 0) return false;
*out = sv_getprop_fallback_len(js, with_obj, a->str, (ant_offset_t)a->len);
return true;
}
static inline ant_value_t sv_op_with_get_var(
sv_vm_t *vm, ant_t *js,
sv_frame_t *frame,
sv_func_t *func, uint8_t *ip
) {
uint32_t atom_idx = sv_get_u32(ip + 1);
uint8_t fb_kind = sv_get_u8(ip + 5);
uint16_t fb_idx = sv_get_u16(ip + 6);
sv_atom_t *a = &func->atoms[atom_idx];
if (vtype(frame->with_obj) != T_UNDEF) {
ant_value_t val = js_mkundef();
if (sv_try_get_with_bound_value(js, frame->with_obj, a, &val)) {
if (is_err(val)) return val;
vm->stack[vm->sp++] = val;
return js_mkundef();
}}
if (fb_kind == WITH_FB_GLOBAL) {
ant_value_t val = sv_global_get(js, a->str, a->len);
if (is_undefined(val))
return js_mkerr_typed(
js, JS_ERR_REFERENCE, "'%.*s' is not defined",
(int)a->len, a->str);
vm->stack[vm->sp++] = val;
} else vm->stack[vm->sp++] = sv_with_fallback_get(vm, js, frame, fb_kind, fb_idx);
return js_mkundef();
}
static inline void sv_op_with_put_var(
sv_vm_t *vm, ant_t *js,
sv_frame_t *frame,
sv_func_t *func, uint8_t *ip
) {
uint32_t atom_idx = sv_get_u32(ip + 1);
uint8_t fb_kind = sv_get_u8(ip + 5);
uint16_t fb_idx = sv_get_u16(ip + 6);
sv_atom_t *a = &func->atoms[atom_idx];
ant_value_t val = vm->stack[--vm->sp];
if (vtype(frame->with_obj) != T_UNDEF) {
if (lkp(js, frame->with_obj, a->str, a->len) != 0) {
ant_value_t key = js_mkstr(js, a->str, a->len);
js_setprop(js, frame->with_obj, key, val);
return;
}
}
if (fb_kind == WITH_FB_GLOBAL) {
setprop_interned(js, js->global, a->str, a->len, val);
} else sv_with_fallback_put(vm, js, frame, fb_kind, fb_idx, val);
}
static inline void sv_op_with_del_var(
sv_vm_t *vm, ant_t *js,
sv_frame_t *frame,
sv_func_t *func, uint8_t *ip
) {
uint32_t atom_idx = sv_get_u32(ip + 1);
sv_atom_t *a = &func->atoms[atom_idx];
if (vtype(frame->with_obj) != T_UNDEF) {
if (lkp(js, frame->with_obj, a->str, a->len) != 0) {
ant_value_t result = js_delete_prop(js, frame->with_obj, a->str, a->len);
vm->stack[vm->sp++] = result;
return;
}
}
ant_value_t result = js_delete_prop(js, js->global, a->str, a->len);
bool ok = !is_err(result) && js_truthy(js, result);
vm->stack[vm->sp++] = mkval(T_BOOL, ok);
}
static inline void sv_op_special_obj(
sv_vm_t *vm, ant_t *js,
sv_frame_t *frame, uint8_t *ip
) {
uint8_t which = sv_get_u8(ip + 1);
if (which == 3) {
vm->stack[vm->sp++] = js_get_module_import_binding(js);
return;
}
if (which == 1) {
vm->stack[vm->sp++] = frame ? frame->new_target : js_mkundef();
return;
}
if (which == 2) {
vm->stack[vm->sp++] = frame ? frame->super_val : js_mkundef();
return;
}
if (which != 0 || !frame) {
vm->stack[vm->sp++] = js_mkundef();
return;
}
if (vtype(frame->arguments_obj) == T_UNDEF) {
int mapped_count = sv_frame_is_strict(frame) || !frame->func ? 0 : frame->func->param_count;
if (mapped_count > frame->argc) mapped_count = frame->argc;
frame->arguments_obj = js_create_arguments_object(
js, frame->callee, frame, frame->argc,
mapped_count, sv_frame_is_strict(frame)
);
}
vm->stack[vm->sp++] = frame->arguments_obj;
}
#endif

File Metadata

Mime Type
text/x-c
Expires
Fri, May 1, 2:34 PM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
541499
Default Alt Text
coercion.h (10 KB)

Event Timeline