[njs] Added remaining methods for %TypedArray%.prototype.

Dmitry Volyntsev xeioex at nginx.com
Fri Aug 21 13:08:35 UTC 2020


details:   https://hg.nginx.org/njs/rev/95ec4ee01853
branches:  
changeset: 1499:95ec4ee01853
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Aug 21 13:07:48 2020 +0000
description:
Added remaining methods for %TypedArray%.prototype.

The following methods were added:
every(), filter(), find(), findIndex(), forEach(), includes(),
indexOf(), lastIndexOf(), map(), reduce(), reduceRight(), reverse(),
some().

diffstat:

 src/njs_typed_array.c    |  714 +++++++++++++++++++++++++++++++++++++++++++++-
 src/njs_utils.c          |   56 ---
 src/njs_utils.h          |   57 +++
 src/test/njs_unit_test.c |  391 ++++++++++++++++++++++---
 4 files changed, 1094 insertions(+), 124 deletions(-)

diffs (truncated from 1329 to 1000 lines):

diff -r 15ae88d60ca4 -r 95ec4ee01853 src/njs_typed_array.c
--- a/src/njs_typed_array.c	Wed Aug 19 12:43:23 2020 +0000
+++ b/src/njs_typed_array.c	Fri Aug 21 13:07:48 2020 +0000
@@ -8,6 +8,17 @@
 #include <njs_main.h>
 
 
+typedef enum {
+    NJS_ARRAY_EVERY = 0,
+    NJS_ARRAY_FOR_EACH,
+    NJS_ARRAY_SOME,
+    NJS_ARRAY_FIND,
+    NJS_ARRAY_FIND_INDEX,
+    NJS_ARRAY_FILTER,
+    NJS_ARRAY_MAP,
+} njs_array_iterator_fun_t;
+
+
 njs_typed_array_t *
 njs_typed_array_alloc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_object_type_t type)
@@ -826,6 +837,558 @@ njs_typed_array_prototype_copy_within(nj
 }
 
 
+static njs_int_t
+njs_typed_array_prototype_iterator(njs_vm_t *vm, njs_value_t *args,
+    njs_uint_t nargs, njs_index_t type)
+{
+    double             val;
+    int64_t            i, length;
+    njs_int_t          ret;
+    njs_arr_t          results;
+    njs_value_t        *this, *this_arg, *r;
+    njs_value_t        arguments[4], retval;
+    njs_function_t     *function;
+    njs_typed_array_t  *array, *dst;
+
+    this = njs_argument(args, 0);
+    if (njs_slow_path(!njs_is_typed_array(this))) {
+        njs_type_error(vm, "this is not a typed array");
+        return NJS_ERROR;
+    }
+
+    dst = NULL;
+    array = njs_typed_array(this);
+    length = njs_typed_array_length(array);
+
+    if (njs_slow_path(!njs_is_function(njs_arg(args, nargs, 1)))) {
+        njs_type_error(vm, "callback argument is not callable");
+        return NJS_ERROR;
+    }
+
+    function = njs_function(njs_argument(args, 1));
+    this_arg = njs_arg(args, nargs, 2);
+
+    results.separate = 0;
+    results.pointer = 0;
+
+    switch (type) {
+    case NJS_ARRAY_MAP:
+        njs_set_number(&arguments[0], length);
+        ret = njs_typed_array_species_create(vm, this, njs_value_arg(arguments),
+                                             1, &retval);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NJS_ERROR;
+        }
+
+        dst = njs_typed_array(&retval);
+        break;
+
+    case NJS_ARRAY_FILTER:
+        r = njs_arr_init(vm->mem_pool, &results, NULL, 4, sizeof(njs_value_t));
+        if (njs_slow_path(r == NULL)) {
+            return NJS_ERROR;
+        }
+
+    default:
+        break;
+    }
+
+    for (i = 0; i < length; i++) {
+        val = njs_typed_array_get(array, i);
+
+        arguments[0] = *this_arg;
+        njs_set_number(&arguments[1], val);
+        njs_set_number(&arguments[2], i);
+        njs_set_typed_array(&arguments[3], array);
+
+        ret = njs_function_apply(vm, function, arguments, 4, &vm->retval);
+        if (njs_slow_path(ret != NJS_OK)) {
+            goto exception;
+        }
+
+        switch (type) {
+        case NJS_ARRAY_EVERY:
+            if (!njs_is_true(&vm->retval)) {
+                vm->retval = njs_value_false;
+                goto done;
+            }
+
+            break;
+
+        case NJS_ARRAY_FOR_EACH:
+            break;
+
+        case NJS_ARRAY_SOME:
+        case NJS_ARRAY_FIND:
+        case NJS_ARRAY_FIND_INDEX:
+            if (!njs_is_true(&vm->retval)) {
+                continue;
+            }
+
+            switch (type) {
+            case NJS_ARRAY_SOME:
+                vm->retval = njs_value_true;
+                break;
+
+            case NJS_ARRAY_FIND:
+                njs_set_number(&vm->retval, val);
+                break;
+
+            default:
+                njs_set_number(&vm->retval, i);
+                break;
+            }
+
+            goto done;
+
+        case NJS_ARRAY_MAP:
+            ret = njs_typed_array_set_value(vm, dst, i, &vm->retval);
+            if (njs_slow_path(ret != NJS_OK)) {
+                goto exception;
+            }
+
+            break;
+
+        default:
+            /* NJS_ARRAY_FILTER. */
+
+            if (!njs_is_true(&vm->retval)) {
+                continue;
+            }
+
+            r = njs_arr_add(&results);
+            if (njs_slow_path(r == NULL)) {
+                goto exception;
+            }
+
+            njs_set_number(r, val);
+        }
+    }
+
+    /* Default values. */
+
+    switch (type) {
+    case NJS_ARRAY_EVERY:
+        vm->retval = njs_value_true;
+        break;
+
+    case NJS_ARRAY_SOME:
+        vm->retval = njs_value_false;
+        break;
+
+    case NJS_ARRAY_FOR_EACH:
+    case NJS_ARRAY_FIND:
+        njs_set_undefined(&vm->retval);
+        break;
+
+    case NJS_ARRAY_FIND_INDEX:
+        njs_set_number(&vm->retval, -1);
+        break;
+
+    case NJS_ARRAY_MAP:
+    case NJS_ARRAY_FILTER:
+    default:
+        if (type == NJS_ARRAY_FILTER) {
+            njs_set_number(&arguments[0], results.items);
+            ret = njs_typed_array_species_create(vm, this,
+                                                 njs_value_arg(arguments),
+                                                 1, &retval);
+            if (njs_slow_path(ret != NJS_OK)) {
+                goto exception;
+            }
+
+            dst = njs_typed_array(&retval);
+
+            i = 0;
+
+            while (i < results.items) {
+                r = njs_arr_item(&results, i);
+                ret = njs_typed_array_set_value(vm, dst, i++, r);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    goto exception;
+                }
+            }
+        }
+
+        njs_set_typed_array(&vm->retval, dst);
+        break;
+    }
+
+done:
+
+    ret = NJS_OK;
+
+exception:
+
+    njs_arr_destroy(&results);
+
+    return ret;
+}
+
+
+static njs_int_t
+njs_typed_array_prototype_index_of(njs_vm_t *vm, njs_value_t *args,
+    njs_uint_t nargs, njs_index_t type)
+{
+    double              v;
+    int64_t             i, i64, from, to, index, increment, offset, length;
+    njs_int_t           ret, integer;
+    njs_value_t         *this;
+    const float         *f32;
+    const double        *f64;
+    const uint8_t       *u8;
+    const uint16_t      *u16;
+    const uint32_t      *u32;
+    njs_typed_array_t   *array;
+    njs_array_buffer_t  *buffer;
+
+    this = njs_argument(args, 0);
+    if (njs_slow_path(!njs_is_typed_array(this))) {
+        njs_type_error(vm, "this is not a typed array");
+        return NJS_ERROR;
+    }
+
+    index = -1;
+    array = njs_typed_array(this);
+    length = njs_typed_array_length(array);
+
+    if (!njs_is_number(njs_arg(args, nargs, 1)) || length == 0) {
+        goto done;
+    }
+
+    if (type & 2) {
+        /* lastIndexOf(). */
+
+        if (nargs > 2) {
+            ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &from);
+            if (njs_slow_path(ret != NJS_OK)) {
+                return ret;
+            }
+
+        } else {
+            from = length - 1;
+        }
+
+        if (from >= 0) {
+            from = njs_min(from, length - 1);
+
+        } else if (from < 0) {
+            from += length;
+        }
+
+        to = -1;
+        increment = -1;
+
+        if (from <= to) {
+            goto done;
+        }
+
+    } else {
+        /* indexOf(), includes(). */
+
+        ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &from);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return ret;
+        }
+
+        if (from < 0) {
+            from += length;
+
+            if (from < 0) {
+                from = 0;
+            }
+        }
+
+        to = length;
+        increment = 1;
+
+        if (from >= to) {
+            goto done;
+        }
+    }
+
+    v = njs_number(njs_argument(args, 1));
+
+    i64 = v;
+    integer = (v == i64);
+
+    buffer = array->buffer;
+    offset = array->offset;
+
+    switch (array->type) {
+    case NJS_OBJ_TYPE_INT8_ARRAY:
+        if (integer && ((int8_t) i64 == i64)) {
+            goto search8;
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY:
+    case NJS_OBJ_TYPE_UINT8_ARRAY:
+        if (integer && ((uint8_t) i64 == i64)) {
+search8:
+            u8 = &buffer->u.u8[0];
+            for (i = from; i != to; i += increment) {
+                if (u8[offset + i] == (uint8_t) i64) {
+                    index = i;
+                    break;
+                }
+            }
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_INT16_ARRAY:
+        if (integer && ((int16_t) i64 == i64)) {
+            goto search16;
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_UINT16_ARRAY:
+        if (integer && ((uint16_t) i64 == i64)) {
+search16:
+            u16 = &buffer->u.u16[0];
+            for (i = from; i != to; i += increment) {
+                if (u16[offset + i] == (uint16_t) i64) {
+                    index = i;
+                    break;
+                }
+            }
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_INT32_ARRAY:
+        if (integer && ((int32_t) i64 == i64)) {
+            goto search32;
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_UINT32_ARRAY:
+        if (integer && ((uint32_t) i64 == i64)) {
+search32:
+            u32 = &buffer->u.u32[0];
+            for (i = from; i != to; i += increment) {
+                if (u32[offset + i] == (uint32_t) i64) {
+                    index = i;
+                    break;
+                }
+            }
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_FLOAT32_ARRAY:
+        f32 = &buffer->u.f32[0];
+
+        if (((float) v == v)) {
+            for (i = from; i != to; i += increment) {
+                if (f32[offset + i] == (float) v) {
+                    index = i;
+                    break;
+                }
+            }
+
+        } else if ((type & 1) && isnan(v)) {
+            /* includes() handles NaN. */
+
+            for (i = from; i != to; i += increment) {
+                if (isnan(f32[offset + i])) {
+                    index = i;
+                    break;
+                }
+            }
+        }
+
+        break;
+
+    default:
+
+        /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */
+
+        f64 = &buffer->u.f64[0];
+
+        if ((type & 1) && isnan(v)) {
+            /* includes() handles NaN. */
+
+            for (i = from; i != to; i += increment) {
+                if (isnan(f64[offset + i])) {
+                    index = i;
+                    break;
+                }
+            }
+
+        } else {
+            for (i = from; i != to; i += increment) {
+                if (f64[offset + i] == v) {
+                    index = i;
+                    break;
+                }
+            }
+        }
+    }
+
+done:
+
+    /* Default values. */
+
+    if (type & 1) {
+        njs_set_boolean(&vm->retval, index != -1);
+
+    } else {
+        njs_set_number(&vm->retval, index);
+    }
+
+    return NJS_OK;
+}
+
+
+static njs_int_t
+njs_typed_array_prototype_reduce(njs_vm_t *vm, njs_value_t *args,
+    njs_uint_t nargs, njs_index_t right)
+{
+    int64_t            i, from, to, increment, length;
+    njs_int_t          ret;
+    njs_value_t        *this, accumulator;
+    njs_value_t        arguments[5];
+    njs_function_t     *function;
+    njs_typed_array_t  *array;
+
+    this = njs_argument(args, 0);
+    if (njs_slow_path(!njs_is_typed_array(this))) {
+        njs_type_error(vm, "this is not a typed array");
+        return NJS_ERROR;
+    }
+
+    array = njs_typed_array(this);
+    length = njs_typed_array_length(array);
+
+    if (njs_slow_path(!njs_is_function(njs_arg(args, nargs, 1)))) {
+        njs_type_error(vm, "callback argument is not callable");
+        return NJS_ERROR;
+    }
+
+    function = njs_function(njs_argument(args, 1));
+
+    if (length == 0 && nargs <= 2) {
+        njs_type_error(vm, "Reduce of empty object with no initial value");
+        return NJS_ERROR;
+    }
+
+    if (right) {
+        from = length - 1;
+        to = -1;
+        increment = -1;
+
+    } else {
+        from = 0;
+        to = length;
+        increment = 1;
+    }
+
+    if (nargs > 2) {
+        accumulator = *njs_argument(args, 2);
+
+    } else {
+        njs_set_number(&accumulator, njs_typed_array_get(array, from));
+        from += increment;
+    }
+
+    for (i = from; i != to; i += increment) {
+        njs_set_undefined(&arguments[0]);
+        arguments[1] = accumulator;
+        njs_set_number(&arguments[2], njs_typed_array_get(array, i));
+        njs_set_number(&arguments[3], i);
+        njs_set_typed_array(&arguments[4], array);
+
+        ret =  njs_function_apply(vm, function, arguments, 5, &accumulator);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return ret;
+        }
+    }
+
+    vm->retval = accumulator;
+
+    return NJS_OK;
+}
+
+
+static njs_int_t
+njs_typed_array_prototype_reverse(njs_vm_t *vm, njs_value_t *args,
+    njs_uint_t nargs, njs_index_t unused)
+{
+    double              *f64;
+    uint8_t             *u8;
+    int64_t             i, length;
+    uint16_t            *u16;
+    uint32_t            *u32;
+    njs_value_t         *this;
+    njs_typed_array_t   *array;
+    njs_array_buffer_t  *buffer;
+
+    this = njs_argument(args, 0);
+    if (njs_slow_path(!njs_is_typed_array(this))) {
+        njs_type_error(vm, "this is not a typed array");
+        return NJS_ERROR;
+    }
+
+    array = njs_typed_array(this);
+    length = njs_typed_array_length(array);
+
+    buffer = array->buffer;
+
+    switch (array->type) {
+    case NJS_OBJ_TYPE_UINT8_ARRAY:
+    case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY:
+    case NJS_OBJ_TYPE_INT8_ARRAY:
+        u8 = &buffer->u.u8[array->offset];
+
+        for (i = 0; i < length / 2; i++) {
+            njs_swap_u8(&u8[i], &u8[length - i - 1], 0);
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_INT16_ARRAY:
+    case NJS_OBJ_TYPE_UINT16_ARRAY:
+        u16 = &buffer->u.u16[array->offset];
+
+        for (i = 0; i < length / 2; i++) {
+            njs_swap_u16(&u16[i], &u16[length - i - 1], 0);
+        }
+
+        break;
+
+    case NJS_OBJ_TYPE_INT32_ARRAY:
+    case NJS_OBJ_TYPE_UINT32_ARRAY:
+    case NJS_OBJ_TYPE_FLOAT32_ARRAY:
+        u32 = &buffer->u.u32[array->offset];
+
+        for (i = 0; i < length / 2; i++) {
+            njs_swap_u32(&u32[i], &u32[length - i - 1], 0);
+        }
+
+        break;
+
+    default:
+
+        /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */
+
+        f64 = &buffer->u.f64[array->offset];
+
+        for (i = 0; i < length / 2; i++) {
+            njs_swap_u64(&f64[i], &f64[length - i - 1], 0);
+        }
+    }
+
+    njs_set_typed_array(&vm->retval, array);
+
+    return NJS_OK;
+}
+
+
 static int
 njs_typed_array_compare_i8(const void *a, const void *b, void *c)
 {
@@ -1367,6 +1930,132 @@ static const njs_object_prop_t  njs_type
 
     {
         .type = NJS_PROPERTY,
+        .name = njs_string("copyWithin"),
+        .value = njs_native_function(njs_typed_array_prototype_copy_within, 2),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("every"),
+        .value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
+                                      NJS_ARRAY_EVERY),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("filter"),
+        .value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
+                                      NJS_ARRAY_FILTER),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("find"),
+        .value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
+                                      NJS_ARRAY_FIND),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("findIndex"),
+        .value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
+                                      NJS_ARRAY_FIND_INDEX),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("forEach"),
+        .value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
+                                      NJS_ARRAY_FOR_EACH),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("includes"),
+        .value = njs_native_function2(njs_typed_array_prototype_index_of, 1, 1),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("indexOf"),
+        .value = njs_native_function2(njs_typed_array_prototype_index_of, 1, 0),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("join"),
+        .value = njs_native_function(njs_typed_array_prototype_join, 1),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("fill"),
+        .value = njs_native_function(njs_typed_array_prototype_fill, 1),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("lastIndexOf"),
+        .value = njs_native_function2(njs_typed_array_prototype_index_of, 1, 2),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("map"),
+        .value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
+                                      NJS_ARRAY_MAP),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("reduce"),
+        .value = njs_native_function2(njs_typed_array_prototype_reduce, 1, 0),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("reduceRight"),
+        .value = njs_native_function2(njs_typed_array_prototype_reduce, 1, 1),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("reverse"),
+        .value = njs_native_function(njs_typed_array_prototype_reverse, 0),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
         .name = njs_string("set"),
         .value = njs_native_function(njs_typed_array_prototype_set, 2),
         .writable = 1,
@@ -1383,8 +2072,9 @@ static const njs_object_prop_t  njs_type
 
     {
         .type = NJS_PROPERTY,
-        .name = njs_string("subarray"),
-        .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 0),
+        .name = njs_string("some"),
+        .value = njs_native_function2(njs_typed_array_prototype_iterator, 1,
+                                      NJS_ARRAY_SOME),
         .writable = 1,
         .configurable = 1,
     },
@@ -1399,24 +2089,8 @@ static const njs_object_prop_t  njs_type
 
     {
         .type = NJS_PROPERTY,
-        .name = njs_string("copyWithin"),
-        .value = njs_native_function(njs_typed_array_prototype_copy_within, 2),
-        .writable = 1,
-        .configurable = 1,
-    },
-
-    {
-        .type = NJS_PROPERTY,
-        .name = njs_string("fill"),
-        .value = njs_native_function(njs_typed_array_prototype_fill, 1),
-        .writable = 1,
-        .configurable = 1,
-    },
-
-    {
-        .type = NJS_PROPERTY,
-        .name = njs_string("join"),
-        .value = njs_native_function(njs_typed_array_prototype_join, 1),
+        .name = njs_string("subarray"),
+        .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 0),
         .writable = 1,
         .configurable = 1,
     },
diff -r 15ae88d60ca4 -r 95ec4ee01853 src/njs_utils.c
--- a/src/njs_utils.c	Wed Aug 19 12:43:23 2020 +0000
+++ b/src/njs_utils.c	Fri Aug 21 13:07:48 2020 +0000
@@ -12,62 +12,6 @@ typedef void (*njs_swap_t) (void *a, voi
 
 
 njs_inline void
-njs_swap_u8(void *a, void *b, size_t size)
-{
-    uint8_t  u, *au, *bu;
-
-    au = (uint8_t *) a;
-    bu = (uint8_t *) b;
-
-    u = au[0];
-    au[0] = bu[0];
-    bu[0] = u;
-}
-
-
-njs_inline void
-njs_swap_u16(void *a, void *b, size_t size)
-{
-    uint16_t  u, *au, *bu;
-
-    au = (uint16_t *) a;
-    bu = (uint16_t *) b;
-
-    u = au[0];
-    au[0] = bu[0];
-    bu[0] = u;
-}
-
-
-njs_inline void
-njs_swap_u32(void *a, void *b, size_t size)
-{
-    uint32_t  u, *au, *bu;
-
-    au = (uint32_t *) a;
-    bu = (uint32_t *) b;
-
-    u = au[0];
-    au[0] = bu[0];
-    bu[0] = u;
-}
-
-
-njs_inline void
-njs_swap_u64(void *a, void *b, size_t size)
-{
-    uint64_t  u, *au, *bu;
-
-    au = (uint64_t *) a;
-    bu = (uint64_t *) b;
-
-    u = au[0];
-    au[0] = bu[0];
-    bu[0] = u;
-}
-
-
-njs_inline void
 njs_swap_u128(void *a, void *b, size_t size)
 {
     uint64_t  u, v, *au, *bu;
diff -r 15ae88d60ca4 -r 95ec4ee01853 src/njs_utils.h
--- a/src/njs_utils.h	Wed Aug 19 12:43:23 2020 +0000
+++ b/src/njs_utils.h	Fri Aug 21 13:07:48 2020 +0000
@@ -15,4 +15,61 @@ void njs_qsort(void *base, size_t n, siz
 
 const char *njs_errno_string(int errnum);
 
+
+njs_inline void
+njs_swap_u8(void *a, void *b, size_t size)
+{
+    uint8_t  u, *au, *bu;
+
+    au = (uint8_t *) a;
+    bu = (uint8_t *) b;
+
+    u = au[0];
+    au[0] = bu[0];
+    bu[0] = u;
+}
+
+
+njs_inline void
+njs_swap_u16(void *a, void *b, size_t size)
+{
+    uint16_t  u, *au, *bu;
+
+    au = (uint16_t *) a;
+    bu = (uint16_t *) b;
+
+    u = au[0];
+    au[0] = bu[0];
+    bu[0] = u;
+}
+
+
+njs_inline void
+njs_swap_u32(void *a, void *b, size_t size)
+{
+    uint32_t  u, *au, *bu;
+
+    au = (uint32_t *) a;
+    bu = (uint32_t *) b;
+
+    u = au[0];
+    au[0] = bu[0];
+    bu[0] = u;
+}
+
+
+njs_inline void
+njs_swap_u64(void *a, void *b, size_t size)
+{
+    uint64_t  u, *au, *bu;
+
+    au = (uint64_t *) a;
+    bu = (uint64_t *) b;
+
+    u = au[0];
+    au[0] = bu[0];
+    bu[0] = u;
+}
+
+
 #endif /* _NJS_UTILS_H_INCLUDED_ */
diff -r 15ae88d60ca4 -r 95ec4ee01853 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed Aug 19 12:43:23 2020 +0000
+++ b/src/test/njs_unit_test.c	Fri Aug 21 13:07:48 2020 +0000
@@ -5895,6 +5895,312 @@ static njs_unit_test_t  njs_test[] =
               "           return a.toString() === '4,5,3,4,5'})"),
       njs_str("true") },
 
+    { njs_str("Uint8Array.prototype.every.call(1)"),
+      njs_str("TypeError: this is not a typed array") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([1,2,3])).every(e=>e>0) === true})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([1,2,3])).every(function(e) {"
+              "              if (this != undefined) {throw 'Oops';}"
+              "              return e > 0}) === true})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([1,2,3])).every(function(e) {"
+              "              if (this != 'QQ') {throw 'Oops';}"
+              "              return e > 0}, 'QQ') === true})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([1,2,3])).every(e=>e>1) === false})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,1,2,3,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);"
+              "           return a.every(e=>e<4)})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var collect = []; (new v([42,43])).forEach(e=>collect.push(e)); "
+              "           return collect.join('|') === '42|43'})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([7,10,3,8,5])).filter(q=>q%2).join('|') === '7|3|5'})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,7,10,3,8,5,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 5);"
+              "           return a.filter(q=>q%2).join('|') === '7|3|5'})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,1,2,3,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);"
+              "           return a.find(e=>e>2) === 3})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,1,2,3,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);"
+              "           return a.find(e=>e===255) === undefined})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,1,2,3,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);"
+              "           return a.findIndex(e=>e>2) === 2})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,1,2,3,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);"
+              "           return a.findIndex(e=>e===255) === -1})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([1,2,3])).some(e=>e==2)})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,1,2,3,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);"
+              "           return a.some(e=>e==255)})"),
+      njs_str("false") },
+
+    { njs_str("Uint8Array.prototype.includes.call(1)"),
+      njs_str("TypeError: this is not a typed array") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v()).includes(0, {valueOf(){throw 'Oops'}}) === false})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([0,1,2,3])).includes(2) === true})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([0,1,2,3])).includes(2,3) === false})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = new v(5);"
+              "           return a.includes(0, 4) === true "
+              "                  && a.includes(0, 5) === false;})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([0,1,2,3])).includes(-0) === true})"),
+      njs_str("true") },
+
+    { njs_str(NJS_FLOAT_TYPED_ARRAY_LIST
+              ".every(v=>{return (new v([42, 43, NaN, 41])).includes(NaN) === true})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var orig = new v([255,255,0,2,3,255]);"
+              "           var a = new v(orig.buffer, 2 * v.BYTES_PER_ELEMENT, 3);"


More information about the nginx-devel mailing list