From: Andrey Zelenkov Date: Tue, 4 Apr 2017 03:10:10 +0000 (+0300) Subject: Array.prototype.find() method. X-Git-Tag: 0.1.10~8 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=9e0ab38566564b7e5be16edf21363d75a852cf9e;p=njs.git Array.prototype.find() method. Also introduced njs_array_iterator_sparse_apply() function. --- diff --git a/njs/njs_array.c b/njs/njs_array.c index abfa80e3..381e0822 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -56,6 +56,12 @@ typedef struct { } njs_array_filter_t; +typedef struct { + njs_array_iter_t iter; + njs_value_t value; +} njs_array_find_t; + + typedef struct { njs_array_iter_t iter; njs_array_t *array; @@ -92,6 +98,8 @@ static njs_ret_t njs_array_prototype_every_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static njs_ret_t njs_array_prototype_filter_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); +static njs_ret_t njs_array_prototype_find_continuation(njs_vm_t *vm, + njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static njs_ret_t njs_array_prototype_map_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static nxt_noinline uint32_t njs_array_prototype_map_index(njs_array_t *array, @@ -102,6 +110,8 @@ static nxt_noinline uint32_t njs_array_iterator_index(njs_array_t *array, njs_array_iter_t *iter); static nxt_noinline njs_ret_t njs_array_iterator_apply(njs_vm_t *vm, njs_array_iter_t *iter, njs_value_t *args, nxt_uint_t nargs); +static nxt_noinline njs_ret_t njs_array_prototype_find_apply(njs_vm_t *vm, + njs_array_iter_t *iter, njs_value_t *args, nxt_uint_t nargs); static njs_ret_t njs_array_prototype_reduce_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static njs_ret_t njs_array_prototype_reduce_right_continuation(njs_vm_t *vm, @@ -1464,6 +1474,94 @@ njs_array_prototype_filter_continuation(njs_vm_t *vm, njs_value_t *args, } +static njs_ret_t +njs_array_prototype_find(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, + njs_index_t unused) +{ + nxt_int_t ret; + njs_array_find_t *find; + + ret = njs_array_iterator_args(vm, args, nargs); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + find = njs_vm_continuation(vm); + find->iter.u.cont.function = njs_array_prototype_find_continuation; + find->iter.retval.data.truth = 0; + + return njs_array_prototype_find_continuation(vm, args, nargs, unused); +} + + +static njs_ret_t +njs_array_prototype_find_continuation(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + njs_array_t *array; + njs_array_iter_t *iter; + njs_array_find_t *find; + const njs_value_t *retval; + + retval = &njs_value_void; + + find = njs_vm_continuation(vm); + iter = &find->iter; + + if (!njs_is_true(&iter->retval)) { + array = args[0].data.u.array; + iter->index++; + + if (iter->index < iter->length && iter->index < array->length) { + /* GC: find->value */ + find->value = array->start[iter->index]; + + return njs_array_prototype_find_apply(vm, iter, args, nargs); + } + + } else { + if (njs_is_valid(&find->value)) { + retval = &find->value; + } + } + + vm->retval = *retval; + + return NXT_OK; +} + + +static nxt_noinline njs_ret_t +njs_array_prototype_find_apply(njs_vm_t *vm, njs_array_iter_t *iter, + njs_value_t *args, nxt_uint_t nargs) +{ + uint32_t n; + const njs_value_t *value; + njs_value_t arguments[4]; + + /* GC: array elt, array */ + + value = (nargs > 2) ? &args[2] : &njs_value_void; + arguments[0] = *value; + + n = iter->index; + value = &args[0].data.u.array->start[n]; + + if (!njs_is_valid(value)) { + value = &njs_value_void; + } + + arguments[1] = *value; + + njs_number_set(&arguments[2], n); + + arguments[3] = args[0]; + + return njs_function_apply(vm, args[1].data.u.function, arguments, 4, + (njs_index_t) &iter->retval); +} + + static njs_ret_t njs_array_prototype_map(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) @@ -2041,6 +2139,14 @@ static const njs_object_prop_t njs_array_prototype_properties[] = njs_continuation_size(njs_array_filter_t), 0), }, + /* ES6. */ + { + .type = NJS_METHOD, + .name = njs_string("find"), + .value = njs_native_function(njs_array_prototype_find, + njs_continuation_size(njs_array_find_t), 0), + }, + { .type = NJS_METHOD, .name = njs_string("map"), diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 7891ea5a..73cc5ded 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -2883,6 +2883,49 @@ static njs_unit_test_t njs_test[] = "a.filter(function(v, i, a) { a[i+1] = v+10; return true })"), nxt_string("1,11,21,31,41,51,61") }, + { nxt_string("var a = [];" + "a.find(function(v, i, a) { return v > 1 })"), + nxt_string("undefined") }, + + { nxt_string("var a = [,NaN,0,-1];" + "a.find(function(v, i, a) { return v > 1 })"), + nxt_string("undefined") }, + + { nxt_string("var a = [,NaN,0,-1,2];" + "a.find(function(v, i, a) { return v > 1 })"), + nxt_string("2") }, + + { nxt_string("var a = [1,2,3,-1,5];" + "a.find(function(v, i, a) { return v > 1 })"), + nxt_string("2") }, + + { nxt_string("var a = [,1,,-1,5];" + "a.find(function(v, i, a) { return v > 1 })"), + nxt_string("5") }, + + { nxt_string("var a = [,1,,-1,5,6];" + "a.find(function(v, i, a) { return v > 1 })"), + nxt_string("5") }, + + { nxt_string("[].find(function(v) { return (v === undefined) })"), + nxt_string("undefined") }, + + { nxt_string("var a = [,3];" + "a.find(function(v) { return (v === 3 || v === undefined) })"), + nxt_string("undefined") }, + + { nxt_string("var a = [1,,3];" + "a.find(function(v) { return (v === 3 || v === undefined) })"), + nxt_string("undefined") }, + + { nxt_string("var a = [1,2,3,4,5,6];" + "a.find(function(v, i, a) { a.shift(); return v == 3 })"), + nxt_string("3") }, + + { nxt_string("var a = [1,2,3,4,5,6];" + "a.find(function(v, i, a) { a.shift(); return v == 4 })"), + nxt_string("undefined") }, + { nxt_string("var a = [];" "a.map(function(v, i, a) { return v + 1 })"), nxt_string("") },