[njs] Fixed Array.prototype.reverse() according to the specification.
Dmitry Volyntsev
xeioex at nginx.com
Tue May 26 18:36:21 UTC 2020
details: https://hg.nginx.org/njs/rev/db77713e0536
branches:
changeset: 1401:db77713e0536
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue May 26 16:35:11 2020 +0000
description:
Fixed Array.prototype.reverse() according to the specification.
diffstat:
src/njs_array.c | 104 +++++++++++++++++++++++++++++++++++++++-------
src/test/njs_unit_test.c | 17 +++++++
2 files changed, 104 insertions(+), 17 deletions(-)
diffs (160 lines):
diff -r b5f4b848c60f -r db77713e0536 src/njs_array.c
--- a/src/njs_array.c Tue May 26 16:34:45 2020 +0000
+++ b/src/njs_array.c Tue May 26 16:35:11 2020 +0000
@@ -1306,10 +1306,9 @@ static njs_int_t
njs_array_prototype_reverse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- int64_t length;
- njs_int_t ret;
- njs_uint_t i, n;
- njs_value_t value, *this;
+ int64_t length, l, h;
+ njs_int_t ret, lret, hret;
+ njs_value_t value, lvalue, hvalue, *this;
njs_array_t *array;
this = njs_argument(args, 0);
@@ -1324,31 +1323,102 @@ njs_array_prototype_reverse(njs_vm_t *vm
return ret;
}
- if (njs_slow_path(length == 0)) {
+ if (njs_slow_path(length < 2)) {
vm->retval = *this;
return NJS_OK;
}
- if (njs_slow_path(!njs_is_fast_array(this))) {
- njs_internal_error(vm, "reverse() is not implemented yet for objects");
- return NJS_ERROR;
- }
-
if (njs_is_fast_array(this)) {
array = njs_array(this);
- length = array->length;
-
- if (length > 1) {
- for (i = 0, n = length - 1; i < n; i++, n--) {
- value = array->start[i];
- array->start[i] = array->start[n];
- array->start[n] = value;
+
+ for (l = 0, h = length - 1; l < h; l++, h--) {
+ if (njs_fast_path(njs_is_valid(&array->start[l]))) {
+ lvalue = array->start[l];
+ lret = NJS_OK;
+
+ } else {
+ lret = njs_value_property_i64(vm, this, l, &lvalue);
+ if (njs_slow_path(lret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+ }
+
+ if (njs_fast_path(njs_is_valid(&array->start[h]))) {
+ hvalue = array->start[h];
+ hret = NJS_OK;
+
+ } else {
+ hret = njs_value_property_i64(vm, this, h, &hvalue);
+ if (njs_slow_path(hret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+ }
+
+ if (lret == NJS_OK) {
+ array->start[h] = lvalue;
+
+ if (hret == NJS_OK) {
+ array->start[l] = hvalue;
+
+ } else {
+ array->start[h] = njs_value_invalid;
+ }
+
+ } else if (hret == NJS_OK) {
+ array->start[l] = hvalue;
+ array->start[h] = njs_value_invalid;
}
}
njs_set_array(&vm->retval, array);
+ return NJS_OK;
}
+ for (l = 0, h = length - 1; l < h; l++, h--) {
+ lret = njs_value_property_i64(vm, this, l, &lvalue);
+ if (njs_slow_path(lret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ hret = njs_value_property_i64(vm, this, h, &hvalue);
+ if (njs_slow_path(hret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ if (lret == NJS_OK) {
+ ret = njs_value_property_i64_set(vm, this, h, &lvalue);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ if (hret == NJS_OK) {
+ ret = njs_value_property_i64_set(vm, this, l, &hvalue);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ } else {
+ ret = njs_value_property_i64_delete(vm, this, l, &value);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+ }
+
+ } else if (hret == NJS_OK) {
+ ret = njs_value_property_i64_set(vm, this, l, &hvalue);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_value_property_i64_delete(vm, this, h, &value);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+ }
+ }
+
+ vm->retval = *this;
+
return NJS_OK;
}
diff -r b5f4b848c60f -r db77713e0536 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Tue May 26 16:34:45 2020 +0000
+++ b/src/test/njs_unit_test.c Tue May 26 16:35:11 2020 +0000
@@ -4509,6 +4509,23 @@ static njs_unit_test_t njs_test[] =
{ njs_str("var o = {1:true, 2:'', length:-2}; Array.prototype.reverse.call(o) === o"),
njs_str("true") },
+ { njs_str("["
+ " ['a','b','c'],"
+ " ['a','b','c','d'],"
+ " [,'b','c','d'],"
+ " ['a','b','c',],"
+ " [,'b','c',],"
+ "]"
+ ".map(v=>Object.defineProperty(v, 1, {value:v[1], enumerable:false}))"
+ ".map(v=>v.reverse().join(''))"),
+ njs_str("cba,dcba,dcb,cba,cb") },
+
+ { njs_str("Array.prototype[1] = 1; var x = [0]; x.length = 2; x.reverse(); x"),
+ njs_str("1,0") },
+
+ { njs_str("Array.prototype[0] = 0; var x = [,1]; x.reverse(); x"),
+ njs_str("1,0") },
+
{ njs_str("var a = [1,2,3,4]; a.indexOf()"),
njs_str("-1") },
More information about the nginx-devel
mailing list