From: Dmitry Volyntsev Date: Wed, 3 Jun 2020 18:40:09 +0000 (+0000) Subject: Introduced njs_array_copy_within(). X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=31b1b91d7cd4a53dd0b28b28fbe713043927fc8d;p=njs.git Introduced njs_array_copy_within(). --- diff --git a/src/njs_array.c b/src/njs_array.c index d4ac5492..519eba93 100644 --- a/src/njs_array.c +++ b/src/njs_array.c @@ -250,6 +250,60 @@ done: } +static njs_int_t +njs_array_copy_within(njs_vm_t *vm, njs_value_t *array, int64_t to_pos, + int64_t from_pos, int64_t count, njs_bool_t forward) +{ + int64_t i, from, to; + njs_int_t ret; + njs_array_t *arr; + njs_value_t value; + + if (njs_fast_path(njs_is_fast_array(array) && count > 0)) { + arr = njs_array(array); + + memmove(&arr->start[to_pos], &arr->start[from_pos], + count * sizeof(njs_value_t)); + + return NJS_OK; + } + + if (!forward) { + from_pos += count - 1; + to_pos += count - 1; + } + + for (i = 0; i < count; i++) { + if (forward) { + from = from_pos + i; + to = to_pos + i; + + } else { + from = from_pos - i; + to = to_pos - i; + } + + ret = njs_value_property_i64(vm, array, from, &value); + if (njs_slow_path(ret == NJS_ERROR)) { + return NJS_ERROR; + } + + if (ret == NJS_OK) { + ret = njs_value_property_i64_set(vm, array, to, &value); + + } else { + ret = njs_value_property_i64_delete(vm, array, to, NULL); + } + + if (njs_slow_path(ret == NJS_ERROR)) { + return NJS_ERROR; + } + } + + return NJS_OK; +} + + njs_int_t njs_array_add(njs_vm_t *vm, njs_array_t *array, njs_value_t *value) { @@ -3423,11 +3477,9 @@ static njs_int_t njs_array_prototype_copy_within(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int8_t direction; int64_t length, count, to, from, end; njs_int_t ret; - njs_array_t *array; - njs_value_t *this, *value, prop; + njs_value_t *this, *value; this = njs_argument(args, 0); @@ -3471,53 +3523,10 @@ njs_array_prototype_copy_within(njs_vm_t *vm, njs_value_t *args, count = njs_min(end - from, length - to); - if (from < to && from + count) { - direction = -1; - from = from + count - 1; - to = to + count - 1; - - } else { - direction = 1; - } - njs_vm_retval_set(vm, this); - if (njs_fast_path(njs_is_fast_array(this))) { - array = njs_array(this); - - while (count-- > 0) { - array->start[to] = array->start[from]; - - from = from + direction; - to = to + direction; - } - - return NJS_OK; - } - - while (count-- > 0) { - ret = njs_value_property_i64(vm, this, from, &prop); - - if (ret == NJS_OK) { - ret = njs_value_property_i64_set(vm, this, to, &prop); - - } else { - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - - ret = njs_value_property_i64_delete(vm, this, to, NULL); - } - - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - - from = from + direction; - to = to + direction; - } - - return NJS_OK; + return njs_array_copy_within(vm, this, to, from, count, + !(from < to && to < from + count)); } diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 30487b10..25a527c7 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -4165,6 +4165,9 @@ static njs_unit_test_t njs_test[] = { njs_str("[0, 1, , , 1].copyWithin(0, 1, 4)"), njs_str("1,,,,1") }, + { njs_str("[0, 1, 2, 3].copyWithin(0, 1, -10)"), + njs_str("0,1,2,3") }, + { njs_str("var o = [0, 1, , , 1].copyWithin(0, 1, 4); typeof o"), njs_str("object") }, @@ -4184,6 +4187,10 @@ static njs_unit_test_t njs_test[] = "Object.keys(obj) + '|' + Object.values(obj)"), njs_str("length,1,2,3,4,5,0|5,a,b,c,d,e,c") }, + { njs_str("var o = {length:1}; Object.defineProperty(o, '0', {get:()=>{throw Error('Oops')}});" + "Array.prototype.copyWithin.call(o, 0, 0)"), + njs_str("Error: Oops") }, + { njs_str("Array.prototype.slice(1)"), njs_str("") },