From: Vadim Zhestikov Date: Mon, 10 Nov 2025 17:50:48 +0000 (-0800) Subject: Added Object.hasOwn(). X-Git-Tag: 0.9.5~29 X-Git-Url: http://www.kaiwu.me/postgresql/commit/static/gitweb.js?a=commitdiff_plain;h=56dae7f64ffe3c93cd72f5a2d77c8a21d3cc1b58;p=njs.git Added Object.hasOwn(). --- diff --git a/src/njs_atom_defs.h b/src/njs_atom_defs.h index 6328c34b..35dcbe12 100644 --- a/src/njs_atom_defs.h +++ b/src/njs_atom_defs.h @@ -286,6 +286,7 @@ NJS_DEF_STRING(getMonth, "getMonth", 0, 0) NJS_DEF_STRING(global, "global", 0, 0) NJS_DEF_STRING(globalThis, "globalThis", 0, 0) NJS_DEF_STRING(groups, "groups", 0, 0) +NJS_DEF_STRING(hasOwn, "hasOwn", 0, 0) NJS_DEF_STRING(hasOwnProperty, "hasOwnProperty", 0, 0) NJS_DEF_STRING(hasInstance, "hasInstance", 0, 0) NJS_DEF_STRING(hypot, "hypot", 0, 0) diff --git a/src/njs_object.c b/src/njs_object.c index 0f277fea..97f17d58 100644 --- a/src/njs_object.c +++ b/src/njs_object.c @@ -31,6 +31,9 @@ static njs_int_t njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_object_set_prototype(njs_vm_t *vm, njs_object_t *object, const njs_value_t *value); +static njs_int_t njs_object_prototype_has_own_property(njs_vm_t *vm, + njs_value_t *args, njs_uint_t nargs, njs_index_t magic, + njs_value_t *retval); njs_object_t * @@ -2274,8 +2277,10 @@ static const njs_object_prop_init_t njs_object_constructor_properties[] = NJS_DECLARE_PROP_NATIVE(STRING_assign, njs_object_assign, 2, 0), NJS_DECLARE_PROP_NATIVE(STRING_is, njs_object_is, 2, 0), -}; + NJS_DECLARE_PROP_NATIVE(STRING_hasOwn, + njs_object_prototype_has_own_property, 2, 1), +}; const njs_object_init_t njs_object_constructor_init = { njs_object_constructor_properties, @@ -2590,27 +2595,47 @@ njs_object_to_string(njs_vm_t *vm, njs_value_t *this, njs_value_t *retval) static njs_int_t njs_object_prototype_has_own_property(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) + njs_uint_t nargs, njs_index_t magic, njs_value_t *retval) { njs_int_t ret; njs_value_t *value, *property, lvalue; njs_property_query_t pq; - property = njs_lvalue_arg(&lvalue, args, nargs, 1); + if (magic == 0) { + /* hasOwnProperty. */ - if (njs_slow_path(!njs_is_key(property))) { - ret = njs_value_to_key(vm, property, property); - if (njs_slow_path(ret != NJS_OK)) { + property = njs_lvalue_arg(&lvalue, args, nargs, 1 + magic); + if (njs_slow_path(!njs_is_key(property))) { + ret = njs_value_to_key(vm, property, property); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + } + + value = njs_argument(args, magic); + if (njs_is_null_or_undefined(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); return NJS_ERROR; } - } - value = njs_argument(args, 0); + } else { + /* hasOwn. */ - if (njs_is_null_or_undefined(value)) { - njs_type_error(vm, "cannot convert %s argument to object", - njs_type_string(value->type)); - return NJS_ERROR; + value = njs_lvalue_arg(&lvalue, args, nargs, magic); + if (njs_is_null_or_undefined(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); + return NJS_ERROR; + } + + property = njs_lvalue_arg(&lvalue, args, nargs, 1 + magic); + if (njs_slow_path(!njs_is_key(property))) { + ret = njs_value_to_key(vm, property, property); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + } } njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 67c57d19..c0f1f1d3 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -15108,6 +15108,83 @@ static njs_unit_test_t njs_test[] = { njs_str("Object.prototype.hasOwnProperty('hasOwnProperty')"), njs_str("true") }, + { njs_str("var o = {a:1}; Object.hasOwn(o, 'a')"), + njs_str("true") }, + + { njs_str("var o = Object.create({a:2}); Object.hasOwn(o, 'a')"), + njs_str("false") }, + + { njs_str("var o = {a:1}; Object.hasOwn(o, 'b')"), + njs_str("false") }, + + { njs_str("var o = Object.create(null); o.a = 1; Object.hasOwn(o, 'a')"), + njs_str("true") }, + + { njs_str("var o = Object.create(null); Object.hasOwn(o, 'hasOwnProperty')"), + njs_str("false") }, + + { njs_str("var o = {hasOwnProperty: 1}; Object.hasOwn(o, 'hasOwnProperty')"), + njs_str("true") }, + + { njs_str("var o = {a:1}; o.hasOwnProperty = function(){return false}; " + "Object.hasOwn(o, 'a')"), + njs_str("true") }, + + { njs_str("Object.hasOwn(null, 'a')"), + njs_str("TypeError: cannot convert null argument to object") }, + + { njs_str("Object.hasOwn(undefined, 'a')"), + njs_str("TypeError: cannot convert undefined argument to object") }, + + { njs_str("Object.hasOwn(1, 'toString')"), + njs_str("true") }, + + { njs_str("Object.hasOwn('abc', '0')"), + njs_str("true") }, + + { njs_str("Object.hasOwn('abc', '3')"), + njs_str("false") }, + + { njs_str("Object.hasOwn('abc', 'length')"), + njs_str("true") }, + + { njs_str("Object.hasOwn([1,2], '0')"), + njs_str("true") }, + + { njs_str("Object.hasOwn([,2], '0')"), + njs_str("false") }, + + { njs_str("Object.hasOwn([,2], '1')"), + njs_str("true") }, + + { njs_str("Object.hasOwn([], 'length')"), + njs_str("true") }, + + { njs_str("var s = Symbol('test'); var o = {}; o[s] = 1; Object.hasOwn(o, s)"), + njs_str("true") }, + + { njs_str("var s1 = Symbol('test'); var s2 = Symbol('test'); " + "var o = {}; o[s1] = 1; Object.hasOwn(o, s2)"), + njs_str("false") }, + + { njs_str("Object.hasOwn({}, Symbol.iterator)"), + njs_str("false") }, + + { njs_str("Object.hasOwn()"), + njs_str("TypeError: cannot convert ") }, + + { njs_str("Object.hasOwn({})"), + njs_str("false") }, + + { njs_str("var o = {}; Object.hasOwn(o)"), + njs_str("false") }, + + { njs_str("Object.hasOwn.length"), + njs_str("2") }, + + { njs_str("Object.hasOwn.name"), + njs_str("hasOwn") }, + { njs_str("var o = {};" "Object.defineProperty(o, 'a', {get:undefined, set:undefined}).a"), njs_str("undefined") },