[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