[njs] Added %TypedArray% remaining methods.

Dmitry Volyntsev xeioex at nginx.com
Mon Sep 7 12:45:11 UTC 2020


details:   https://hg.nginx.org/njs/rev/0e927892f0bf
branches:  
changeset: 1518:0e927892f0bf
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Mon Sep 07 12:44:07 2020 +0000
description:
Added %TypedArray% remaining methods.

The following methods were added: of(), from().

diffstat:

 src/njs_typed_array.c    |  255 +++++++++++++++++++++++++++++++++++++---------
 src/njs_value.h          |    4 +
 src/test/njs_unit_test.c |   52 +++++++++
 3 files changed, 260 insertions(+), 51 deletions(-)

diffs (355 lines):

diff -r f4fe4b4b9730 -r 0e927892f0bf src/njs_typed_array.c
--- a/src/njs_typed_array.c	Thu Sep 03 13:30:17 2020 +0000
+++ b/src/njs_typed_array.c	Mon Sep 07 12:44:07 2020 +0000
@@ -268,6 +268,194 @@ njs_typed_array_constructor(njs_vm_t *vm
 
 
 static njs_int_t
+njs_typed_array_create(njs_vm_t *vm, njs_value_t *constructor,
+    njs_value_t *args, njs_uint_t nargs, njs_value_t *retval)
+{
+    njs_int_t     ret;
+    njs_value_t   this;
+    njs_object_t  *object;
+
+    object = njs_function_new_object(vm, constructor);
+    if (njs_slow_path(object == NULL)) {
+        return NJS_ERROR;
+    }
+
+    njs_set_object(&this, object);
+
+    ret = njs_function_call2(vm, njs_function(constructor), &this, args,
+                             nargs, retval, 1);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
+    if (njs_slow_path(!njs_is_typed_array(retval))) {
+        njs_type_error(vm, "Derived TypedArray constructor "
+                       "returned not a typed array");
+        return NJS_ERROR;
+    }
+
+    if (njs_slow_path(nargs == 1 && njs_is_number(&args[0])
+                      && njs_typed_array_length(njs_typed_array(retval))
+                         < njs_number(&args[0])))
+    {
+        njs_type_error(vm, "Derived TypedArray constructor "
+                       "returned too short array");
+        return NJS_ERROR;
+    }
+
+    return NJS_OK;
+}
+
+
+static njs_int_t
+njs_typed_array_species_create(njs_vm_t *vm, njs_value_t *exemplar,
+    njs_value_t *args, njs_uint_t nargs, njs_value_t *retval)
+{
+    njs_int_t          ret;
+    njs_value_t        constructor;
+    njs_typed_array_t  *array;
+
+    array = njs_typed_array(exemplar);
+
+    njs_set_function(&constructor, &vm->constructors[array->type]);
+
+    ret = njs_value_species_constructor(vm, exemplar, &constructor,
+                                        &constructor);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return ret;
+    }
+
+    return njs_typed_array_create(vm, &constructor, args, nargs, retval);
+}
+
+
+static njs_int_t
+njs_typed_array_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+    njs_index_t unused)
+{
+    double             num;
+    uint32_t           length, i;
+    njs_int_t          ret;
+    njs_value_t        *this;
+    njs_value_t        argument;
+    njs_typed_array_t  *array;
+
+    this = njs_argument(args, 0);
+
+    if (njs_slow_path(!njs_is_constructor(this))) {
+        njs_type_error(vm, "%s is not a constructor",
+                       njs_type_string(this->type));
+        return NJS_ERROR;
+    }
+
+    length = nargs - 1;
+
+    njs_set_number(&argument, length);
+    ret = njs_typed_array_create(vm, this, &argument, 1, &vm->retval);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
+    array = njs_typed_array(&vm->retval);
+
+    for (i = 0; i < length; i++) {
+        ret = njs_value_to_number(vm, njs_argument(args, i + 1), &num);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NJS_ERROR;
+        }
+
+        njs_typed_array_prop_set(vm, array, i, num);
+    }
+
+    njs_set_typed_array(&vm->retval, array);
+
+    return NJS_OK;
+}
+
+
+static njs_int_t
+njs_typed_array_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+    njs_index_t unused)
+{
+    double             num;
+    int64_t            length, i;
+    njs_int_t          ret;
+    njs_value_t        *this, *source, *mapfn;
+    njs_value_t        arguments[3], retval;
+    njs_function_t     *function;
+    njs_typed_array_t  *array;
+
+    this = njs_argument(args, 0);
+
+    if (njs_slow_path(!njs_is_constructor(this))) {
+        njs_type_error(vm, "%s is not a constructor",
+                       njs_type_string(this->type));
+        return NJS_ERROR;
+    }
+
+    mapfn = njs_arg(args, nargs, 2);
+
+    if (njs_slow_path(!njs_is_function_or_undefined(mapfn))) {
+        njs_type_error(vm, "\"mapfn\" argument is not callable");
+        return NJS_ERROR;
+    }
+
+    function = NULL;
+    if (njs_is_function(mapfn)) {
+        function = njs_function(mapfn);
+    }
+
+    source = njs_arg(args, nargs, 1);
+
+    ret = njs_value_to_object(vm, source);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return ret;
+    }
+
+    ret = njs_object_length(vm, source, &length);
+    if (njs_slow_path(ret == NJS_ERROR)) {
+        return ret;
+    }
+
+    njs_set_number(&arguments[0], length);
+    ret = njs_typed_array_create(vm, this, arguments, 1, &vm->retval);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
+    array = njs_typed_array(&vm->retval);
+    arguments[0] = *njs_arg(args, nargs, 3);
+
+    for (i = 0; i < length; i++) {
+        ret = njs_value_property_i64(vm, source, i, &retval);
+        if (njs_slow_path(ret == NJS_ERROR)) {
+            return NJS_ERROR;
+        }
+
+        if (function != NULL) {
+            arguments[1] = retval;
+            njs_set_number(&arguments[2], i);
+            ret = njs_function_apply(vm, function, arguments, 3, &retval);
+            if (njs_slow_path(ret != NJS_OK)) {
+                return NJS_ERROR;
+            }
+        }
+
+        ret = njs_value_to_number(vm, &retval, &num);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NJS_ERROR;
+        }
+
+        njs_typed_array_prop_set(vm, array, i, num);
+    }
+
+    njs_set_typed_array(&vm->retval, array);
+
+    return NJS_OK;
+}
+
+
+static njs_int_t
 njs_typed_array_get_this(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t unused)
 {
@@ -770,57 +958,6 @@ njs_typed_array_prototype_fill(njs_vm_t 
 
 
 static njs_int_t
-njs_typed_array_species_create(njs_vm_t *vm, njs_value_t *exemplar,
-    njs_value_t *args, njs_uint_t nargs, njs_value_t *retval)
-{
-    njs_int_t          ret;
-    njs_value_t        this, constructor;
-    njs_object_t       *object;
-    njs_typed_array_t  *array;
-
-    array = njs_typed_array(exemplar);
-
-    njs_set_function(&constructor, &vm->constructors[array->type]);
-
-    ret = njs_value_species_constructor(vm, exemplar, &constructor,
-                                        &constructor);
-    if (njs_slow_path(ret != NJS_OK)) {
-        return ret;
-    }
-
-    object = njs_function_new_object(vm, &constructor);
-    if (njs_slow_path(object == NULL)) {
-        return NJS_ERROR;
-    }
-
-    njs_set_object(&this, object);
-
-    ret = njs_function_call2(vm, njs_function(&constructor), &this,
-                             args, nargs, retval, 1);
-    if (njs_slow_path(ret != NJS_OK)) {
-        return NJS_ERROR;
-    }
-
-    if (njs_slow_path(!njs_is_typed_array(retval))) {
-        njs_type_error(vm, "Derived TypedArray constructor "
-                       "returned not a typed array");
-        return NJS_ERROR;
-    }
-
-    if (njs_slow_path(nargs == 1 && njs_is_number(&args[0])
-                      && njs_typed_array_length(njs_typed_array(retval))
-                         < njs_number(&args[0])))
-    {
-        njs_type_error(vm, "Derived TypedArray constructor "
-                       "returned too short array");
-        return NJS_ERROR;
-    }
-
-    return NJS_OK;
-}
-
-
-static njs_int_t
 njs_typed_array_prototype_slice(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t copy)
 {
@@ -2013,6 +2150,22 @@ static const njs_object_prop_t  njs_type
         .configurable = 1,
         .enumerable = 0,
     },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("of"),
+        .value = njs_native_function(njs_typed_array_of, 0),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("from"),
+        .value = njs_native_function(njs_typed_array_from, 1),
+        .writable = 1,
+        .configurable = 1,
+    },
 };
 
 
diff -r f4fe4b4b9730 -r 0e927892f0bf src/njs_value.h
--- a/src/njs_value.h	Thu Sep 03 13:30:17 2020 +0000
+++ b/src/njs_value.h	Mon Sep 07 12:44:07 2020 +0000
@@ -676,6 +676,10 @@ typedef struct {
     ((value)->type == NJS_FUNCTION || (value)->type == NJS_UNDEFINED)
 
 
+#define njs_is_constructor(value)                                             \
+    (njs_is_function(value) && njs_function(value)->ctor)
+
+
 #define njs_is_regexp(value)                                                  \
     ((value)->type == NJS_REGEXP)
 
diff -r f4fe4b4b9730 -r 0e927892f0bf src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Thu Sep 03 13:30:17 2020 +0000
+++ b/src/test/njs_unit_test.c	Mon Sep 07 12:44:07 2020 +0000
@@ -5473,6 +5473,58 @@ static njs_unit_test_t  njs_test[] =
       njs_str("true") },
 
     { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.of(); return njs.dump(a) === `${v.name} []`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.of(1); return njs.dump(a) === `${v.name} [1]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.of(1,2,3,4,5); return njs.dump(a) === `${v.name} [1,2,3,4,5]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{ try{ v.of(Symbol()); } catch (e) { return e.name === 'TypeError'}})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{ try{ v.of.call(()=>1); } catch (e) { return e.name === 'TypeError'}})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{ try{ v.of.call(function(){}); } catch (e) { return e.name === 'TypeError'}})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.from([1,2]); return njs.dump(a) === `${v.name} [1,2]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.from([1,2], v=>2*v); return njs.dump(a) === `${v.name} [2,4]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.from([1,2], function(v){return v * this.m}, {m:3}); "
+              "           return njs.dump(a) === `${v.name} [3,6]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.from([1,2], function(v){return v * this.m}, {m:3}); "
+              "           return njs.dump(a) === `${v.name} [3,6]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_INT_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.from({length:3, 0:1, 2:'a'});"
+              "           return njs.dump(a) === `${v.name} [1,0,0]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_FLOAT_TYPED_ARRAY_LIST
+              ".every(v=>{var a = v.from({length:3, 0:1, 2:'a'});"
+              "           return njs.dump(a) === `${v.name} [1,NaN,NaN]`})"),
+      njs_str("true") },
+
+    { njs_str(NJS_TYPED_ARRAY_LIST
               ".every(v=>{var a = new v(4); a.fill(42); return (a[0] === 42 && a.length == 4)})"),
       njs_str("true") },
 


More information about the nginx-devel mailing list