diff --git a/examples/results.txt b/examples/results.txt index 8348062..1ffa054 100644 --- a/examples/results.txt +++ b/examples/results.txt @@ -514,23 +514,23 @@ compat-table/es6/Array.prototype.keys.js: OK compat-table/es6/Array.prototype.splice.js: failed compat-table/es6/Array.prototype.values.js: OK compat-table/es6/Date.prototype.Symbol.toPrimitive.js: OK -compat-table/es6/Function.name.accessor.js: failed -compat-table/es6/Function.name.bound.js: failed +compat-table/es6/Function.name.accessor.js: OK +compat-table/es6/Function.name.bound.js: OK compat-table/es6/Function.name.class-expression.js: OK -compat-table/es6/Function.name.class-object-method.js: failed -compat-table/es6/Function.name.class-prototype.js: failed +compat-table/es6/Function.name.class-object-method.js: OK +compat-table/es6/Function.name.class-prototype.js: OK compat-table/es6/Function.name.class-statement.js: OK -compat-table/es6/Function.name.class-static.js: failed -compat-table/es6/Function.name.class-variable.js: failed -compat-table/es6/Function.name.configurable.js: failed +compat-table/es6/Function.name.class-static.js: OK +compat-table/es6/Function.name.class-variable.js: OK +compat-table/es6/Function.name.configurable.js: OK compat-table/es6/Function.name.expression.js: OK -compat-table/es6/Function.name.new-Function.js: failed +compat-table/es6/Function.name.new-Function.js: OK compat-table/es6/Function.name.object-method.js: OK compat-table/es6/Function.name.shorthand.js: OK compat-table/es6/Function.name.shorthand.no-lexical.js: OK compat-table/es6/Function.name.statement.js: OK -compat-table/es6/Function.name.symbol-keyed.js: failed -compat-table/es6/Function.name.variable.js: failed +compat-table/es6/Function.name.symbol-keyed.js: OK +compat-table/es6/Function.name.variable.js: OK compat-table/es6/Map.Symbol.species.js: OK compat-table/es6/Map.constructor-accepts-null.js: OK compat-table/es6/Map.constructor-arguments.js: OK diff --git a/include/internal.h b/include/internal.h index 9a7cc79..6d2d5d2 100644 --- a/include/internal.h +++ b/include/internal.h @@ -451,6 +451,28 @@ ant_value_t js_for_in_keys(ant_t *js, ant_value_t obj); ant_value_t js_delete_prop(ant_t *js, ant_value_t obj, const char *key, size_t len); ant_value_t js_delete_sym_prop(ant_t *js, ant_value_t obj, ant_value_t sym); +ant_value_t js_cfunc_promote(ant_t *js, ant_value_t cfunc); +ant_value_t js_cfunc_expose_named(ant_t *js, ant_value_t cfunc, const char *name, size_t name_len); +ant_value_t js_set_function_name(ant_t *js, ant_value_t fn, const char *name, size_t name_len); + +ant_value_t js_set_function_name_prefixed( + ant_t *js, ant_value_t fn, + const char *prefix, size_t prefix_len, + const char *name, size_t name_len +); + +ant_value_t js_set_function_name_from_key( + ant_t *js, ant_value_t fn, + ant_value_t key, + const char *prefix, size_t prefix_len +); + +ant_value_t js_maybe_set_function_name_from_key( + ant_t *js, ant_value_t fn, + ant_value_t key, + const char *prefix, size_t prefix_len +); + bool is_proxy(ant_value_t obj); bool strict_eq_values(ant_t *js, ant_value_t l, ant_value_t r); bool js_deep_equal(ant_t *js, ant_value_t a, ant_value_t b, bool strict); @@ -628,9 +650,6 @@ static inline void js_set_module_default(ant_t *js, ant_value_t lib, ant_value_t js_set_slot_wb(js, lib, SLOT_DEFAULT, ctor_fn); } -ant_value_t js_cfunc_promote(ant_t *js, ant_value_t cfunc); -ant_value_t js_cfunc_expose_named(ant_t *js, ant_value_t cfunc, const char *name, size_t name_len); - static inline ant_value_t js_cfunc_lookup_promoted(ant_t *js, ant_value_t cfunc) { uintptr_t ptr = vdata(cfunc); for (uint8_t i = 0; i < js->cfunc_promote_cache.len; i++) if ( diff --git a/include/silver/engine.h b/include/silver/engine.h index 96bce18..2454980 100644 --- a/include/silver/engine.h +++ b/include/silver/engine.h @@ -15,6 +15,12 @@ #include #include +typedef enum { + SV_DEFINE_METHOD_GETTER = 1u << 0, + SV_DEFINE_METHOD_SETTER = 1u << 1, + SV_DEFINE_METHOD_SET_NAME = 1u << 2, +} sv_define_method_flags_t; + typedef enum { #define OP_DEF(name, size, n_pop, n_push, f) OP_##name, #include "silver/opcode.h" diff --git a/include/silver/glue.h b/include/silver/glue.h index 4c51683..b869208 100644 --- a/include/silver/glue.h +++ b/include/silver/glue.h @@ -128,7 +128,7 @@ void jit_helper_define_method_comp( ); void jit_helper_set_name( - sv_vm_t *vm, ant_t *js, ant_value_t fn, + ant_t *js, ant_value_t fn, const char *str, uint32_t len ); diff --git a/src/ant.c b/src/ant.c index 6c36732..aa72652 100644 --- a/src/ant.c +++ b/src/ant.c @@ -5306,6 +5306,9 @@ static ant_value_t build_dynamic_function(ant_t *js, ant_value_t *args, int narg } set_slot(func_obj, SLOT_CFUNC, js_mkfun(builtin_function_empty)); + ant_value_t name_result = js_set_function_name(js, func_obj, "anonymous", 9); + + if (is_err(name_result)) return name_result; ant_value_t func = js_obj_to_func(func_obj); if (!is_async || is_generator) { @@ -5397,6 +5400,13 @@ static ant_value_t build_dynamic_function(ant_t *js, ant_value_t *args, int narg display[n] = '\0'; set_func_code(js, func_obj, display, display_len); + ant_value_t name_result = js_set_function_name(js, func_obj, "anonymous", 9); + if (is_err(name_result)) { + free(display); + free(code_buf); + return name_result; + } + free(display); free(code_buf); @@ -5652,6 +5662,25 @@ static ant_value_t builtin_function_bind(ant_t *js, ant_value_t *args, int nargs int bound_length = orig_length - bound_argc; if (bound_length < 0) bound_length = 0; + const char *target_name = ""; + size_t target_name_len = 0; + ant_value_t target_name_val = js_mkundef(); + if (vtype(func) == T_CFUNC) { + const ant_cfunc_meta_t *meta = js_as_cfunc_meta(func); + if (meta && meta->name) { + target_name = meta->name; + target_name_len = strlen(meta->name); + } + } else { + target_name_val = js_getprop_fallback(js, func, "name"); + } + if (vtype(target_name_val) == T_STR) { + ant_offset_t nlen = 0; + ant_offset_t noff = vstr(js, target_name_val, &nlen); + target_name = (const char *)(uintptr_t)noff; + target_name_len = (size_t)nlen; + } + if (vtype(func) == T_CFUNC) { ant_value_t bound_func = mkobj(js, 0); if (is_err(bound_func)) return bound_func; @@ -5671,6 +5700,10 @@ static ant_value_t builtin_function_bind(ant_t *js, ant_value_t *args, int nargs } js_setprop(js, bound_func, js->length_str, tov((double) bound_length)); + ant_value_t name_result = js_set_function_name_prefixed( + js, bound_func, "bound ", 6, target_name, target_name_len + ); + if (is_err(name_result)) return name_result; ant_value_t proto_setup = setup_func_prototype(js, bound); if (is_err(proto_setup)) return proto_setup; @@ -5749,7 +5782,12 @@ static ant_value_t builtin_function_bind(ant_t *js, ant_value_t *args, int nargs } js_setprop(js, bound_func, js->length_str, tov((double) bound_length)); + ant_value_t name_result = js_set_function_name_prefixed( + js, bound_func, "bound ", 6, + target_name, target_name_len + ); + if (is_err(name_result)) return name_result; ant_value_t bound = mkval(T_FUNC, (uintptr_t)bound_closure); ant_value_t proto_setup = setup_func_prototype(js, bound); @@ -15064,6 +15102,123 @@ static ant_value_t js_cfunc_length_value(ant_value_t cfunc) { return tov((double)js_cfunc_length(cfunc)); } +ant_value_t js_set_function_name(ant_t *js, ant_value_t fn, const char *name, size_t name_len) { + ant_value_t fn_obj = js_as_obj(fn); + ant_object_t *ptr = js_obj_ptr(fn_obj); + + if (!ptr) return js_mkundef(); + if (!name) { + name = ""; + name_len = 0; + } + + const char *name_key = js->intern.name ? js->intern.name : intern_string("name", 4); + if (!name_key) return js_mkerr(js, "oom"); + + ant_value_t name_val = js_mkstr(js, name, name_len); + if (is_err(name_val)) return name_val; + + return mkprop_interned_exact( + js, fn_obj, name_key, name_val, + ANT_PROP_ATTR_CONFIGURABLE + ); +} + +ant_value_t js_set_function_name_prefixed( + ant_t *js, ant_value_t fn, + const char *prefix, size_t prefix_len, + const char *name, size_t name_len +) { + if (!prefix || prefix_len == 0) + return js_set_function_name(js, fn, name, name_len); + + if (!name) { + name = ""; + name_len = 0; + } + + char stack_buf[128]; + size_t total = prefix_len + name_len; + + char *buf = (total + 1 <= sizeof(stack_buf)) ? stack_buf : malloc(total + 1); + if (!buf) return js_mkerr(js, "oom"); + + memcpy(buf, prefix, prefix_len); + memcpy(buf + prefix_len, name, name_len); + buf[total] = '\0'; + + ant_value_t result = js_set_function_name(js, fn, buf, total); + if (buf != stack_buf) free(buf); + + return result; +} + +ant_value_t js_set_function_name_from_key( + ant_t *js, ant_value_t fn, + ant_value_t key, + const char *prefix, size_t prefix_len +) { + if (vtype(key) == T_SYMBOL) { + const char *desc = js_sym_desc(key); + if (!desc) return js_set_function_name_prefixed(js, fn, prefix, prefix_len, "", 0); + + size_t desc_len = strlen(desc); + char stack_buf[128]; + + size_t bracketed_len = desc_len + 2; + char *buf = (bracketed_len + 1 <= sizeof(stack_buf)) ? stack_buf : malloc(bracketed_len + 1); + if (!buf) return js_mkerr(js, "oom"); + + buf[0] = '['; + memcpy(buf + 1, desc, desc_len); + buf[bracketed_len - 1] = ']'; + buf[bracketed_len] = '\0'; + + ant_value_t result = js_set_function_name_prefixed( + js, fn, prefix, prefix_len, + buf, bracketed_len + ); + + if (buf != stack_buf) free(buf); + return result; + } + + ant_value_t key_str = coerce_to_str(js, key); + if (is_err(key_str)) return key_str; + if (vtype(key_str) != T_STR) + return js_set_function_name_prefixed(js, fn, prefix, prefix_len, "", 0); + + ant_offset_t key_len = 0; + ant_offset_t key_off = vstr(js, key_str, &key_len); + + const char *key_ptr = (const char *)(uintptr_t)key_off; + return js_set_function_name_prefixed(js, fn, prefix, prefix_len, key_ptr, (size_t)key_len); +} + +static bool js_function_name_is_inferable(ant_t *js, ant_value_t fn) { + if (vtype(fn) != T_FUNC) return false; + + ant_value_t fn_obj = js_func_obj(fn); + ant_value_t existing = lkp_interned_val(js, fn_obj, js->intern.name); + + if (vtype(existing) == T_UNDEF) return true; + if (vtype(existing) != T_STR) return false; + + ant_offset_t len = 0; + vstr(js, existing, &len); + + return len == 0; +} + +ant_value_t js_maybe_set_function_name_from_key( + ant_t *js, ant_value_t fn, + ant_value_t key, + const char *prefix, size_t prefix_len +) { + if (!js_function_name_is_inferable(js, fn)) return js_mkundef(); + return js_set_function_name_from_key(js, fn, key, prefix, prefix_len); +} + static bool js_cfunc_has_prototype(ant_value_t cfunc) { const ant_cfunc_meta_t *meta = js_as_cfunc_meta(cfunc); return meta && (meta->flags & CFUNC_HAS_PROTOTYPE) != 0; diff --git a/src/silver/compiler.c b/src/silver/compiler.c index 3beec36..d337bcc 100644 --- a/src/silver/compiler.c +++ b/src/silver/compiler.c @@ -482,6 +482,32 @@ static inline void emit_set_function_name( emit_atom_op(c, OP_SET_NAME, name, len); } +static inline bool node_needs_inferred_function_name(const sv_ast_t *node) { + return node && + (node->type == N_FUNC || node->type == N_CLASS) && + (!node->str || node->len == 0); +} + +static void compile_expr_with_inferred_name( + sv_compiler_t *c, sv_ast_t *node, + const char *name, uint32_t len +) { + if (!node_needs_inferred_function_name(node) || !name) { + compile_expr(c, node); + return; + } + + const char *saved_name = c->inferred_name; + uint32_t saved_len = c->inferred_name_len; + + c->inferred_name = name; + c->inferred_name_len = len; + compile_expr(c, node); + + c->inferred_name = saved_name; + c->inferred_name_len = saved_len; +} + static void emit_const_assign_error(sv_compiler_t *c, const char *name, uint32_t len) { static const char prefix[] = "Assignment to constant variable '"; static const char suffix[] = "'"; @@ -2778,8 +2804,9 @@ void compile_object(sv_compiler_t *c, sv_ast_t *node) { if (prop->flags & FN_GETTER || prop->flags & FN_SETTER) { compile_expr(c, prop->right); uint8_t flags = 0; - if (prop->flags & FN_GETTER) flags |= 1; - if (prop->flags & FN_SETTER) flags |= 2; + if (prop->flags & FN_GETTER) flags |= SV_DEFINE_METHOD_GETTER; + if (prop->flags & FN_SETTER) flags |= SV_DEFINE_METHOD_SETTER; + flags |= SV_DEFINE_METHOD_SET_NAME; if (prop->flags & FN_COMPUTED) compile_expr(c, prop->left); else compile_static_property_key(c, prop->left); emit_op(c, OP_SWAP); @@ -2789,15 +2816,11 @@ void compile_object(sv_compiler_t *c, sv_ast_t *node) { compile_expr(c, prop->left); compile_expr(c, prop->right); emit_op(c, OP_DEFINE_METHOD_COMP); - emit(c, 0); + emit(c, node_needs_inferred_function_name(prop->right) ? SV_DEFINE_METHOD_SET_NAME : 0); } else { - if (prop->right && (prop->right->type == N_FUNC || prop->right->type == N_CLASS) && - (!prop->right->str || prop->right->len == 0) && - prop->left && prop->left->type == N_IDENT && !is_quoted_ident_key(prop->left)) { - c->inferred_name = prop->left->str; - c->inferred_name_len = prop->left->len; - } - compile_expr(c, prop->right); + if (prop->left && prop->left->type == N_IDENT && !is_quoted_ident_key(prop->left)) + compile_expr_with_inferred_name(c, prop->right, prop->left->str, prop->left->len); + else compile_expr(c, prop->right); if ((prop->flags & FN_COLON) && prop->left->type == N_IDENT && !is_quoted_ident_key(prop->left) && is_ident_str(prop->left->str, prop->left->len, "__proto__", 9)) { @@ -3595,6 +3618,7 @@ void compile_export_decl(sv_compiler_t *c, sv_ast_t *node) { void compile_var_decl(sv_compiler_t *c, sv_ast_t *node) { sv_var_kind_t kind = node->var_kind; + bool is_using = (kind == SV_VAR_USING || kind == SV_VAR_AWAIT_USING); bool is_await_using = (kind == SV_VAR_AWAIT_USING); bool is_const = (kind == SV_VAR_CONST || is_using); @@ -3608,38 +3632,33 @@ void compile_var_decl(sv_compiler_t *c, sv_ast_t *node) { if (repl_top) { if (!decl->right && kind == SV_VAR_VAR) continue; if (decl->right) { - compile_expr(c, decl->right); - } else { - emit_op(c, OP_UNDEF); - } + if (target->type == N_IDENT) + compile_expr_with_inferred_name(c, decl->right, target->str, target->len); + else compile_expr(c, decl->right); + } else emit_op(c, OP_UNDEF); if (target->type == N_IDENT) { emit_atom_op(c, OP_PUT_GLOBAL, target->str, target->len); - } else { - compile_destructure_pattern(c, target, false, true, - DESTRUCTURE_ASSIGN, kind); - } + } else compile_destructure_pattern(c, target, false, true, DESTRUCTURE_ASSIGN, kind); } else if (kind == SV_VAR_VAR) { if (decl->right) { uint8_t init_type = infer_expr_type(c, decl->right); - compile_expr(c, decl->right); + if (target->type == N_IDENT) + compile_expr_with_inferred_name(c, decl->right, target->str, target->len); + else compile_expr(c, decl->right); if (target->type == N_IDENT) { int idx = resolve_local(c, target->str, target->len); if (idx >= 0 && c->locals[idx].depth != -1) emit_put_local_typed(c, idx, init_type); - else - compile_lhs_set(c, target, false); - } else { - compile_lhs_set(c, target, false); - } + else compile_lhs_set(c, target, false); + } else compile_lhs_set(c, target, false); } } else { if (target->type == N_IDENT) { - int idx = ensure_local_at_depth(c, target->str, target->len, - is_const, c->scope_depth); + int idx = ensure_local_at_depth(c, target->str, target->len, is_const, c->scope_depth); uint8_t init_type = SV_TI_UNKNOWN; if (decl->right) { init_type = infer_expr_type(c, decl->right); - compile_expr(c, decl->right); + compile_expr_with_inferred_name(c, decl->right, target->str, target->len); } else if (!is_const) { emit_op(c, OP_UNDEF); init_type = SV_TI_UNDEF; @@ -4525,13 +4544,15 @@ static void compile_class_method( } uint8_t method_flags = 0; - if (m->flags & FN_GETTER) method_flags |= 1; - if (m->flags & FN_SETTER) method_flags |= 2; + if (m->flags & FN_GETTER) method_flags |= SV_DEFINE_METHOD_GETTER; + if (m->flags & FN_SETTER) method_flags |= SV_DEFINE_METHOD_SETTER; + if (is_fn) method_flags |= SV_DEFINE_METHOD_SET_NAME; if (m->flags & FN_COMPUTED) { if (preeval_key >= 0) emit_get_local(c, preeval_key); else compile_expr(c, m->left); } else compile_static_property_key(c, m->left); + emit_op(c, OP_SWAP); emit_op(c, OP_DEFINE_METHOD_COMP); emit(c, method_flags); @@ -4756,8 +4777,20 @@ void compile_class(sv_compiler_t *c, sv_ast_t *node) { free(computed_key_locals); c->computed_key_locals = NULL; - if (node->str && !has_static_name) { - int atom = add_atom(c, node->str, node->len); + const char *class_name = node->str; + uint32_t class_name_len = node->len; + bool consumed_inferred_name = false; + + if (!class_name && c->inferred_name) { + class_name = c->inferred_name; + class_name_len = c->inferred_name_len; + consumed_inferred_name = true; + } + + if (!has_static_name) { + int atom = class_name + ? add_atom(c, class_name, class_name_len) + : add_atom(c, "", 0); emit_op(c, OP_DEFINE_CLASS); emit_u32(c, (uint32_t)atom); emit(c, 1); @@ -4767,6 +4800,11 @@ void compile_class(sv_compiler_t *c, sv_ast_t *node) { emit(c, 0); } + if (consumed_inferred_name) { + c->inferred_name = NULL; + c->inferred_name_len = 0; + } + emit_u32(c, node->src_off); emit_u32(c, node->src_end); diff --git a/src/silver/glue.c b/src/silver/glue.c index 168c96a..53932f7 100644 --- a/src/silver/glue.c +++ b/src/silver/glue.c @@ -207,14 +207,24 @@ void jit_helper_define_method_comp( ant_value_t obj, ant_value_t key, ant_value_t fn, uint8_t flags ) { ant_value_t desc_obj = js_as_obj(obj); - bool is_getter = (flags & 1) != 0; - bool is_setter = (flags & 2) != 0; + + bool is_getter = (flags & SV_DEFINE_METHOD_GETTER) != 0; + bool is_setter = (flags & SV_DEFINE_METHOD_SETTER) != 0; + + if (flags & SV_DEFINE_METHOD_SET_NAME) { + const char *prefix = is_getter ? "get " : is_setter ? "set " : ""; + size_t prefix_len = is_getter || is_setter ? 4 : 0; + ant_value_t named = js_maybe_set_function_name_from_key(js, fn, key, prefix, prefix_len); + if (is_err(named)) return; + } + if (vtype(key) == T_SYMBOL) { if (is_getter) { js_set_sym_getter_desc(js, desc_obj, key, fn, JS_DESC_E | JS_DESC_C); return; } if (is_setter) { js_set_sym_setter_desc(js, desc_obj, key, fn, JS_DESC_E | JS_DESC_C); return; } js_set_sym(js, obj, key, fn); return; } + ant_value_t key_str = sv_key_to_propstr(js, key); if ((is_getter || is_setter) && vtype(key_str) == T_STR) { ant_offset_t klen = 0; @@ -224,6 +234,7 @@ void jit_helper_define_method_comp( else js_set_setter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C); return; } + if (vtype(key_str) == T_STR) { ant_offset_t klen = 0; ant_offset_t koff = vstr(js, key_str, &klen); @@ -718,34 +729,35 @@ void jit_helper_define_field( js_define_own_prop(js, obj, str, len, val); } - void jit_helper_set_name( - sv_vm_t *vm, ant_t *js, ant_value_t fn, + ant_t *js, ant_value_t fn, const char *str, uint32_t len -) { - ant_value_t name = js_mkstr(js, str, len); - setprop_cstr(js, fn, "name", 4, name); +) { + js_set_function_name(js, fn, str, len); } ant_value_t jit_helper_get_length(sv_vm_t *vm, ant_t *js, ant_value_t obj) { if (vtype(obj) == T_ARR) return tov((double)(uint32_t)js_arr_len(js, obj)); + if (vtype(obj) == T_STR) { ant_flat_string_t *flat = ant_str_flat_ptr(obj); if (flat) { const char *str_data = flat->bytes; ant_offset_t byte_len = flat->len; - return tov((double)(uint32_t)( - str_is_ascii(str_data) - ? byte_len - : utf16_strlen(str_data, byte_len) + return tov((double)(uint32_t)(str_is_ascii(str_data) + ? byte_len + : utf16_strlen(str_data, byte_len) )); } + ant_offset_t byte_len = 0; ant_offset_t off = vstr(js, obj, &byte_len); + const char *str_data = (const char *)(uintptr_t)(off); return tov((double)(uint32_t)utf16_strlen(str_data, byte_len)); } + return js_getprop_fallback(js, obj, "length"); } diff --git a/src/silver/ops/objects.h b/src/silver/ops/objects.h index bccf14f..309cec2 100644 --- a/src/silver/ops/objects.h +++ b/src/silver/ops/objects.h @@ -20,8 +20,16 @@ static inline void sv_op_define_method( ant_value_t obj = vm->stack[vm->sp - 1]; ant_value_t desc_obj = js_as_obj(obj); - bool is_getter = (flags & 1) != 0; - bool is_setter = (flags & 2) != 0; + bool is_getter = (flags & SV_DEFINE_METHOD_GETTER) != 0; + bool is_setter = (flags & SV_DEFINE_METHOD_SETTER) != 0; + + if (flags & SV_DEFINE_METHOD_SET_NAME) { + const char *prefix = is_getter ? "get " : is_setter ? "set " : ""; + size_t prefix_len = is_getter || is_setter ? 4 : 0; + ant_value_t key = js_mkstr(js, a->str, a->len); + ant_value_t named = js_maybe_set_function_name_from_key(js, fn, key, prefix, prefix_len); + if (is_err(named)) return; + } if (is_getter) { js_set_getter_desc(js, desc_obj, a->str, a->len, fn, JS_DESC_E | JS_DESC_C); @@ -46,14 +54,24 @@ static inline void sv_op_define_method_comp( ant_value_t key = vm->stack[--vm->sp]; ant_value_t obj = vm->stack[vm->sp - 1]; ant_value_t desc_obj = js_as_obj(obj); - bool is_getter = (flags & 1) != 0; - bool is_setter = (flags & 2) != 0; + + bool is_getter = (flags & SV_DEFINE_METHOD_GETTER) != 0; + bool is_setter = (flags & SV_DEFINE_METHOD_SETTER) != 0; + + if (flags & SV_DEFINE_METHOD_SET_NAME) { + const char *prefix = is_getter ? "get " : is_setter ? "set " : ""; + size_t prefix_len = is_getter || is_setter ? 4 : 0; + ant_value_t named = js_maybe_set_function_name_from_key(js, fn, key, prefix, prefix_len); + if (is_err(named)) return; + } + if (vtype(key) == T_SYMBOL) { if (is_getter) { js_set_sym_getter_desc(js, desc_obj, key, fn, JS_DESC_E | JS_DESC_C); return; } if (is_setter) { js_set_sym_setter_desc(js, desc_obj, key, fn, JS_DESC_E | JS_DESC_C); return; } js_set_sym(js, obj, key, fn); return; } + ant_value_t key_str = sv_key_to_propstr(js, key); if ((is_getter || is_setter) && vtype(key_str) == T_STR) { ant_offset_t klen = 0; @@ -63,6 +81,7 @@ static inline void sv_op_define_method_comp( else js_set_setter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C); return; } + if (vtype(key_str) == T_STR) { ant_offset_t klen = 0; ant_offset_t koff = vstr(js, key_str, &klen); @@ -78,15 +97,13 @@ static inline void sv_op_set_name( uint32_t atom_idx = sv_get_u32(ip + 1); sv_atom_t *a = &func->atoms[atom_idx]; ant_value_t fn = vm->stack[vm->sp - 1]; - ant_value_t name = js_mkstr(js, a->str, a->len); - setprop_cstr(js, fn, "name", 4, name); + js_set_function_name(js, fn, a->str, a->len); } static inline void sv_op_set_name_comp(sv_vm_t *vm, ant_t *js) { ant_value_t key = vm->stack[vm->sp - 1]; ant_value_t fn = vm->stack[vm->sp - 2]; - ant_value_t name = coerce_to_str(js, key); - setprop_cstr(js, fn, "name", 4, name); + js_set_function_name_from_key(js, fn, key, "", 0); } static inline void sv_op_set_proto(sv_vm_t *vm, ant_t *js) { @@ -263,15 +280,15 @@ static inline void sv_op_define_class( if (is_object_type(object_proto)) js_set_proto_init(proto, object_proto); } } - if (parent_is_callable) { - if (vtype(ctor) == T_FUNC) { - sv_closure_t *c = js_func_closure(ctor); - c->super_val = parent; - c->call_flags |= SV_CALL_HAS_SUPER; - } + + if (parent_is_callable) if (vtype(ctor) == T_FUNC) { + sv_closure_t *c = js_func_closure(ctor); + c->super_val = parent; + c->call_flags |= SV_CALL_HAS_SUPER; } - if (vtype(ctor) == T_FUNC) js_mark_constructor(js_func_obj(ctor), true); + if (vtype(ctor) == T_FUNC) + js_mark_constructor(js_func_obj(ctor), true); if ( vtype(ctor) == T_FUNC && func->source && @@ -285,8 +302,8 @@ static inline void sv_op_define_class( ant_value_t ctor_obj = (vtype(ctor) == T_FUNC) ? js_func_obj(ctor) : ctor; js_mkprop_fast(js, ctor_obj, "prototype", 9, proto); - if (a && a->len > 0) - setprop_cstr(js, ctor, "name", 4, js_mkstr(js, a->str, a->len)); + if (has_name) + js_set_function_name(js, ctor, a ? a->str : "", a ? a->len : 0); vm->stack[vm->sp - 2] = ctor; vm->stack[vm->sp - 1] = proto; diff --git a/src/silver/swarm.c b/src/silver/swarm.c index 22926e9..19a597d 100644 --- a/src/silver/swarm.c +++ b/src/silver/swarm.c @@ -2255,8 +2255,7 @@ sv_jit_func_t sv_jit_compile(ant_t *js, sv_func_t *func, sv_closure_t *hint_clos MIR_T_I32, "slot_count"); MIR_item_t set_name_proto = MIR_new_proto(ctx, "sn_proto", - 0, NULL, 5, - MIR_T_I64, "vm", + 0, NULL, 4, MIR_T_I64, "js", MIR_JSVAL, "fn", MIR_T_P, "str", @@ -8005,10 +8004,9 @@ sv_jit_func_t sv_jit_compile(ant_t *js, sv_func_t *func, sv_closure_t *hint_clos sv_atom_t *atom = &func->atoms[atom_idx]; MIR_reg_t fn_val = vstack_top(&vs); MIR_append_insn(ctx, jit_func, - MIR_new_call_insn(ctx, 7, + MIR_new_call_insn(ctx, 6, MIR_new_ref_op(ctx, set_name_proto), MIR_new_ref_op(ctx, imp_set_name), - MIR_new_reg_op(ctx, r_vm), MIR_new_reg_op(ctx, r_js), MIR_new_reg_op(ctx, fn_val), MIR_new_uint_op(ctx, (uint64_t)(uintptr_t)atom->str),