From 2acbc402c1249031b3e32cebcb2e50d71ee9608f Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Thu, 8 Jun 2017 14:18:37 +0300 Subject: [PATCH] Object.prototype.hasOwnProperty() method. --- njs/njs_object.c | 50 ++++++++++++++++++++++++++++++++++++++++ njs/njs_vm.h | 13 +++++++++++ njs/test/njs_unit_test.c | 42 +++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/njs/njs_object.c b/njs/njs_object.c index d2f1c382..e83255ea 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -882,6 +882,49 @@ found: } +static njs_ret_t +njs_object_prototype_has_own_property(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + uint32_t index; + nxt_int_t ret; + njs_array_t *array; + const njs_value_t *retval; + nxt_lvlhsh_query_t lhq; + + retval = &njs_string_false; + + if (njs_is_object(&args[0])) { + + if (njs_is_array(&args[0])) { + array = args[0].data.u.array; + index = njs_string_to_index(&args[1]); + + if (index < array->length && njs_is_valid(&array->start[index])) { + retval = &njs_string_true; + goto done; + } + } + + njs_string_get(&args[1], &lhq.key); + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + lhq.proto = &njs_object_hash_proto; + + ret = nxt_lvlhsh_find(&args[0].data.u.object->hash, &lhq); + + if (ret == NXT_OK) { + retval = &njs_string_true; + } + } + +done: + + vm->retval = *retval; + + return NXT_OK; +} + + static const njs_object_prop_t njs_object_prototype_properties[] = { { @@ -907,6 +950,13 @@ static const njs_object_prop_t njs_object_prototype_properties[] = .name = njs_string("toString"), .value = njs_native_function(njs_object_prototype_to_string, 0, 0), }, + + { + .type = NJS_METHOD, + .name = njs_string("hasOwnProperty"), + .value = njs_native_function(njs_object_prototype_has_own_property, 0, + NJS_OBJECT_ARG, NJS_STRING_ARG), + }, }; diff --git a/njs/njs_vm.h b/njs/njs_vm.h index 61d06189..057920a9 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -408,6 +408,19 @@ typedef njs_ret_t (*njs_vmcode_operation_t)(njs_vm_t *vm, njs_value_t *value1, #define njs_string_truth(value, size) +#define njs_string_get(value, str) \ + do { \ + if ((value)->short_string.size != NJS_STRING_LONG) { \ + (str)->length = (value)->short_string.size; \ + (str)->start = (value)->short_string.start; \ + \ + } else { \ + (str)->length = (value)->data.string_size; \ + (str)->start = (value)->data.u.string->start; \ + } \ + } while (0) + + #define njs_string_short_start(value) \ (value)->short_string.start diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 97a82a9c..ffcedc27 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -5932,6 +5932,48 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = {}; Object.defineProperty(o)"), nxt_string("TypeError") }, + { nxt_string("var o = {a:1}; o.hasOwnProperty('a')"), + nxt_string("true") }, + + { nxt_string("var o = Object.create({a:2}); o.hasOwnProperty('a')"), + nxt_string("false") }, + + { nxt_string("var o = {a:1}; o.hasOwnProperty('b')"), + nxt_string("false") }, + + { nxt_string("var a = []; a.hasOwnProperty('0')"), + nxt_string("false") }, + + { nxt_string("var a = [,,]; a.hasOwnProperty('0')"), + nxt_string("false") }, + + { nxt_string("var a = [3,,]; a.hasOwnProperty('0')"), + nxt_string("true") }, + + { nxt_string("var a = [,4]; a.hasOwnProperty('1')"), + nxt_string("true") }, + + { nxt_string("var a = [3,4]; a.hasOwnProperty('2')"), + nxt_string("false") }, + + { nxt_string("var a = [3,4]; a.one = 1; a.hasOwnProperty('one')"), + nxt_string("true") }, + + { nxt_string("var o = {a:1}; o.hasOwnProperty(o)"), + nxt_string("false") }, + + { nxt_string("var o = {a:1}; o.hasOwnProperty(1)"), + nxt_string("false") }, + + { nxt_string("var o = {a:1}; o.hasOwnProperty()"), + nxt_string("false") }, + + { nxt_string("1..hasOwnProperty('b')"), + nxt_string("false") }, + + { nxt_string("'s'.hasOwnProperty('b')"), + nxt_string("false") }, + { nxt_string("var d = new Date(''); d +' '+ d.getTime()"), nxt_string("Invalid Date NaN") }, -- 2.47.3