diff --git a/examples/results.txt b/examples/results.txt index 29ab2dd..3e0ec19 100644 --- a/examples/results.txt +++ b/examples/results.txt @@ -771,7 +771,7 @@ compat-table/es6/class.extends-null.js: OK compat-table/es6/class.extends.js: OK compat-table/es6/class.implicit-strict.js: failed compat-table/es6/class.lexical-name.js: OK -compat-table/es6/class.methods-not-enumerable.js: failed +compat-table/es6/class.methods-not-enumerable.js: OK compat-table/es6/class.new-target.js: OK compat-table/es6/class.optional-semicolons.js: OK compat-table/es6/class.prototype-methods.js: OK diff --git a/examples/spec/classes.js b/examples/spec/classes.js index 7aa72a8..c620d4c 100644 --- a/examples/spec/classes.js +++ b/examples/spec/classes.js @@ -30,6 +30,7 @@ class Calculator { let calc = new Calculator(10); test('method add', calc.add(5), 15); test('method subtract', calc.subtract(3), 12); +test('prototype method not enumerable', Calculator.prototype.propertyIsEnumerable('add'), false); class Point { setCoords(x, y) { @@ -184,6 +185,8 @@ class Static { test('static property', Static.value, 42); test('static method', Static.method(), 'static'); +test('static method not enumerable', Static.propertyIsEnumerable('method'), false); +test('static field enumerable', Static.propertyIsEnumerable('value'), true); class StaticNamedElements { static(value) { diff --git a/include/silver/engine.h b/include/silver/engine.h index 731442b..99e821d 100644 --- a/include/silver/engine.h +++ b/include/silver/engine.h @@ -19,6 +19,7 @@ typedef enum { SV_DEFINE_METHOD_GETTER = 1u << 0, SV_DEFINE_METHOD_SETTER = 1u << 1, SV_DEFINE_METHOD_SET_NAME = 1u << 2, + SV_DEFINE_METHOD_NON_ENUM = 1u << 3, } sv_define_method_flags_t; typedef enum { diff --git a/src/silver/compiler.c b/src/silver/compiler.c index fc7e51f..088a369 100644 --- a/src/silver/compiler.c +++ b/src/silver/compiler.c @@ -4547,6 +4547,7 @@ static void compile_class_method( 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 (is_fn || (m->flags & (FN_GETTER | FN_SETTER))) method_flags |= SV_DEFINE_METHOD_NON_ENUM; if (m->flags & FN_COMPUTED) { if (preeval_key >= 0) emit_get_local(c, preeval_key); diff --git a/src/silver/glue.c b/src/silver/glue.c index b4cf424..8af6e75 100644 --- a/src/silver/glue.c +++ b/src/silver/glue.c @@ -211,6 +211,14 @@ void jit_helper_define_method_comp( bool is_getter = (flags & SV_DEFINE_METHOD_GETTER) != 0; bool is_setter = (flags & SV_DEFINE_METHOD_SETTER) != 0; + uint8_t data_attrs = (flags & SV_DEFINE_METHOD_NON_ENUM) + ? (ANT_PROP_ATTR_WRITABLE | ANT_PROP_ATTR_CONFIGURABLE) + : ANT_PROP_ATTR_DEFAULT; + + uint8_t accessor_desc = (flags & SV_DEFINE_METHOD_NON_ENUM) + ? JS_DESC_C + : (JS_DESC_E | JS_DESC_C); + 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; @@ -219,9 +227,9 @@ void jit_helper_define_method_comp( } 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); + if (is_getter) { js_set_sym_getter_desc(js, desc_obj, key, fn, accessor_desc); return; } + if (is_setter) { js_set_sym_setter_desc(js, desc_obj, key, fn, accessor_desc); return; } + mkprop(js, obj, key, fn, data_attrs); return; } @@ -230,8 +238,8 @@ void jit_helper_define_method_comp( ant_offset_t klen = 0; ant_offset_t koff = vstr(js, key_str, &klen); const char *kptr = (const char *)(uintptr_t)(koff); - if (is_getter) js_set_getter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C); - else js_set_setter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C); + if (is_getter) js_set_getter_desc(js, desc_obj, kptr, klen, fn, accessor_desc); + else js_set_setter_desc(js, desc_obj, kptr, klen, fn, accessor_desc); return; } @@ -239,8 +247,8 @@ void jit_helper_define_method_comp( ant_offset_t klen = 0; ant_offset_t koff = vstr(js, key_str, &klen); const char *kptr = (const char *)(uintptr_t)(koff); - js_define_own_prop(js, obj, kptr, (size_t)klen, fn); - } else mkprop(js, obj, key_str, fn, 0); + mkprop(js, obj, js_mkstr(js, kptr, (size_t)klen), fn, data_attrs); + } else mkprop(js, obj, key_str, fn, data_attrs); } static ant_value_t jit_iter_advance_from_buf( diff --git a/src/silver/ops/objects.h b/src/silver/ops/objects.h index 309cec2..307b188 100644 --- a/src/silver/ops/objects.h +++ b/src/silver/ops/objects.h @@ -23,6 +23,14 @@ static inline void sv_op_define_method( bool is_getter = (flags & SV_DEFINE_METHOD_GETTER) != 0; bool is_setter = (flags & SV_DEFINE_METHOD_SETTER) != 0; + uint8_t data_attrs = (flags & SV_DEFINE_METHOD_NON_ENUM) + ? (ANT_PROP_ATTR_WRITABLE | ANT_PROP_ATTR_CONFIGURABLE) + : ANT_PROP_ATTR_DEFAULT; + + uint8_t accessor_desc = (flags & SV_DEFINE_METHOD_NON_ENUM) + ? JS_DESC_C + : (JS_DESC_E | JS_DESC_C); + 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; @@ -32,17 +40,17 @@ static inline void sv_op_define_method( } if (is_getter) { - js_set_getter_desc(js, desc_obj, a->str, a->len, fn, JS_DESC_E | JS_DESC_C); + js_set_getter_desc(js, desc_obj, a->str, a->len, fn, accessor_desc); return; } if (is_setter) { - js_set_setter_desc(js, desc_obj, a->str, a->len, fn, JS_DESC_E | JS_DESC_C); + js_set_setter_desc(js, desc_obj, a->str, a->len, fn, accessor_desc); return; } ant_value_t key = js_mkstr(js, a->str, a->len); - mkprop(js, obj, key, fn, 0); + mkprop(js, obj, key, fn, data_attrs); } static inline void sv_op_define_method_comp( @@ -58,6 +66,14 @@ static inline void sv_op_define_method_comp( bool is_getter = (flags & SV_DEFINE_METHOD_GETTER) != 0; bool is_setter = (flags & SV_DEFINE_METHOD_SETTER) != 0; + uint8_t data_attrs = (flags & SV_DEFINE_METHOD_NON_ENUM) + ? (ANT_PROP_ATTR_WRITABLE | ANT_PROP_ATTR_CONFIGURABLE) + : ANT_PROP_ATTR_DEFAULT; + + uint8_t accessor_desc = (flags & SV_DEFINE_METHOD_NON_ENUM) + ? JS_DESC_C + : (JS_DESC_E | JS_DESC_C); + 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; @@ -66,9 +82,9 @@ static inline void sv_op_define_method_comp( } 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); + if (is_getter) { js_set_sym_getter_desc(js, desc_obj, key, fn, accessor_desc); return; } + if (is_setter) { js_set_sym_setter_desc(js, desc_obj, key, fn, accessor_desc); return; } + mkprop(js, obj, key, fn, data_attrs); return; } @@ -77,8 +93,8 @@ static inline void sv_op_define_method_comp( ant_offset_t klen = 0; ant_offset_t koff = vstr(js, key_str, &klen); const char *kptr = (const char *)(uintptr_t)(koff); - if (is_getter) js_set_getter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C); - else js_set_setter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C); + if (is_getter) js_set_getter_desc(js, desc_obj, kptr, klen, fn, accessor_desc); + else js_set_setter_desc(js, desc_obj, kptr, klen, fn, accessor_desc); return; } @@ -86,8 +102,8 @@ static inline void sv_op_define_method_comp( ant_offset_t klen = 0; ant_offset_t koff = vstr(js, key_str, &klen); const char *kptr = (const char *)(uintptr_t)(koff); - js_define_own_prop(js, obj, kptr, (size_t)klen, fn); - } else mkprop(js, obj, key_str, fn, 0); + mkprop(js, obj, js_mkstr(js, kptr, (size_t)klen), fn, data_attrs); + } else mkprop(js, obj, key_str, fn, data_attrs); } static inline void sv_op_set_name(