[njs] Added conversion of this value to object in Array.prototype functions.
Alexander Borisov
alexander.borisov at nginx.com
Mon Oct 28 13:51:16 UTC 2019
details: https://hg.nginx.org/njs/rev/3c15734aaeb8
branches:
changeset: 1204:3c15734aaeb8
user: Alexander Borisov <alexander.borisov at nginx.com>
date: Mon Oct 28 16:50:20 2019 +0300
description:
Added conversion of this value to object in Array.prototype functions.
This closes #231 issue on GitHub.
diffstat:
src/njs_array.c | 159 ++++++++++++++++++++++++----------------------
src/njs_value.c | 33 +++++++++
src/njs_value.h | 1 +
src/test/njs_unit_test.c | 6 +-
4 files changed, 120 insertions(+), 79 deletions(-)
diffs (396 lines):
diff -r c43ebb4722fc -r 3c15734aaeb8 src/njs_array.c
--- a/src/njs_array.c Mon Oct 28 16:10:17 2019 +0300
+++ b/src/njs_array.c Mon Oct 28 16:50:20 2019 +0300
@@ -419,16 +419,19 @@ static njs_int_t
njs_array_prototype_slice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- int64_t start, end, length;
- uint32_t object_length;
- njs_int_t ret;
-
- if (njs_slow_path(njs_is_null_or_undefined(njs_arg(args, nargs, 0)))) {
- njs_type_error(vm, "cannot convert undefined to object");
- return NJS_ERROR;
+ int64_t start, end, length;
+ uint32_t object_length;
+ njs_int_t ret;
+ njs_value_t *value;
+
+ value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- ret = njs_object_length(vm, njs_arg(args, nargs, 0), &object_length);
+ ret = njs_object_length(vm, value, &object_length);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
@@ -480,7 +483,7 @@ njs_array_prototype_slice(njs_vm_t *vm,
}
}
- return njs_array_prototype_slice_copy(vm, &args[0], start, length);
+ return njs_array_prototype_slice_copy(vm, value, start, length);
}
@@ -601,9 +604,9 @@ njs_array_prototype_push(njs_vm_t *vm, n
value = njs_arg(args, nargs, 0);
length = 0;
- if (njs_slow_path(njs_is_null_or_undefined(value))) {
- njs_type_error(vm, "Cannot convert undefined or null to object");
- return NJS_ERROR;
+ ret = njs_value_to_object(vm, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
if (njs_is_array(&args[0])) {
@@ -662,9 +665,9 @@ njs_array_prototype_pop(njs_vm_t *vm, nj
value = njs_arg(args, nargs, 0);
- if (njs_slow_path(njs_is_null_or_undefined(value))) {
- njs_type_error(vm, "Cannot convert undefined or null to object");
- return NJS_ERROR;
+ ret = njs_value_to_object(vm, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
njs_set_undefined(&vm->retval);
@@ -722,9 +725,9 @@ njs_array_prototype_unshift(njs_vm_t *vm
length = 0;
n = nargs - 1;
- if (njs_slow_path(njs_is_null_or_undefined(value))) {
- njs_type_error(vm, "Cannot convert undefined or null to object");
- return NJS_ERROR;
+ ret = njs_value_to_object(vm, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
if (njs_is_array(value)) {
@@ -863,9 +866,9 @@ njs_array_prototype_shift(njs_vm_t *vm,
value = njs_arg(args, nargs, 0);
length = 0;
- if (njs_slow_path(njs_is_null_or_undefined(value))) {
- njs_type_error(vm, "Cannot convert undefined or null to object");
- return NJS_ERROR;
+ ret = njs_value_to_object(vm, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
njs_set_undefined(&vm->retval);
@@ -944,17 +947,19 @@ njs_array_prototype_splice(njs_vm_t *vm,
njs_value_t *value;
njs_array_t *array, *deleted;
- if (njs_slow_path(njs_is_null_or_undefined(njs_arg(args, nargs, 0)))) {
- njs_type_error(vm, "cannot convert undefined to object");
- return NJS_ERROR;
+ value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
array = NULL;
start = 0;
delete = 0;
- if (njs_is_array(&args[0])) {
- array = njs_array(&args[0]);
+ if (njs_is_array(value)) {
+ array = njs_array(value);
length = array->length;
if (nargs > 1) {
@@ -1059,17 +1064,20 @@ static njs_int_t
njs_array_prototype_reverse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
+ njs_int_t ret;
njs_uint_t i, n, length;
- njs_value_t value;
+ njs_value_t value, *this;
njs_array_t *array;
- if (njs_slow_path(njs_is_null_or_undefined(njs_arg(args, nargs, 0)))) {
- njs_type_error(vm, "cannot convert undefined to object");
- return NJS_ERROR;
+ this = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, this);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- if (njs_is_array(&args[0])) {
- array = njs_array(&args[0]);
+ if (njs_is_array(this)) {
+ array = njs_array(this);
length = array->length;
if (length > 1) {
@@ -1084,7 +1092,7 @@ njs_array_prototype_reverse(njs_vm_t *vm
} else {
/* STUB */
- vm->retval = args[0];
+ vm->retval = *this;
}
return NJS_OK;
@@ -1131,9 +1139,9 @@ njs_array_prototype_join(njs_vm_t *vm, n
njs_value_t *value, *values;
njs_string_prop_t separator, string;
- if (njs_slow_path(njs_is_null_or_undefined(njs_arg(args, nargs, 0)))) {
- njs_type_error(vm, "cannot convert undefined to object");
- return NJS_ERROR;
+ ret = njs_value_to_object(vm, &args[0]);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
if (nargs > 1 && !njs_is_string(&args[1])) {
@@ -1672,10 +1680,16 @@ njs_array_prototype_concat(njs_vm_t *vm,
njs_index_t unused)
{
uint64_t length;
+ njs_int_t ret;
njs_uint_t i;
njs_value_t *value;
njs_array_t *array;
+ ret = njs_value_to_object(vm, &args[0]);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
length = 0;
for (i = 0; i < nargs; i++) {
@@ -1749,12 +1763,13 @@ njs_array_prototype_index_of(njs_vm_t *v
njs_int_t ret;
njs_array_iterator_args_t iargs;
- if (njs_slow_path(njs_is_null_or_undefined(njs_arg(args, nargs, 0)))) {
- njs_type_error(vm, "unexpected iterator arguments");
- return NJS_ERROR;
+ iargs.value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, iargs.value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- iargs.value = njs_argument(args, 0);
iargs.argument = njs_arg(args, nargs, 1);
ret = njs_value_length(vm, iargs.value, &length);
@@ -1804,12 +1819,13 @@ njs_array_prototype_last_index_of(njs_vm
njs_int_t ret;
njs_array_iterator_args_t iargs;
- if (njs_slow_path(njs_is_null_or_undefined(njs_arg(args, nargs, 0)))) {
- njs_type_error(vm, "unexpected iterator arguments");
- return NJS_ERROR;
+ iargs.value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, iargs.value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- iargs.value = njs_argument(args, 0);
iargs.argument = njs_arg(args, nargs, 1);
ret = njs_value_length(vm, iargs.value, &length);
@@ -1895,12 +1911,13 @@ njs_array_prototype_includes(njs_vm_t *v
njs_int_t ret;
njs_array_iterator_args_t iargs;
- if (njs_slow_path(njs_is_null_or_undefined(njs_arg(args, nargs, 0)))) {
- njs_type_error(vm, "unexpected iterator arguments");
- return NJS_ERROR;
+ iargs.value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, iargs.value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- iargs.value = njs_argument(args, 0);
iargs.argument = njs_arg(args, nargs, 1);
ret = njs_value_length(vm, iargs.value, &length);
@@ -1958,25 +1975,12 @@ njs_array_prototype_fill(njs_vm_t *vm, n
njs_int_t i, ret;
njs_array_t *array;
njs_value_t name, *this, *value;
- njs_object_t *object;
this = njs_arg(args, nargs, 0);
- if (njs_is_primitive(this)) {
- if (njs_is_null_or_undefined(this)) {
- njs_type_error(vm, "\"this\" argument cannot be "
- "undefined or null value");
- return NJS_ERROR;
- }
-
- object = njs_object_value_alloc(vm, this, this->type);
- if (njs_slow_path(object == NULL)) {
- return NJS_ERROR;
- }
-
- njs_set_type_object(&vm->retval, object, object->type);
-
- return NJS_OK;
+ ret = njs_value_to_object(vm, this);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
array = NULL;
@@ -2063,12 +2067,13 @@ njs_array_validate_args(njs_vm_t *vm, nj
{
njs_int_t ret;
- if (njs_is_null_or_undefined(njs_arg(args, nargs, 0))) {
- goto failed;
+ iargs->value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, iargs->value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- iargs->value = njs_argument(args, 0);
-
ret = njs_value_length(vm, iargs->value, &iargs->to);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
@@ -2422,12 +2427,13 @@ njs_array_prototype_map(njs_vm_t *vm, nj
njs_array_t *array;
njs_array_iterator_args_t iargs;
- if (njs_is_null_or_undefined(njs_arg(args, nargs, 0))) {
- goto unexpected_args;
+ iargs.value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, iargs.value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- iargs.value = njs_argument(args, 0);
-
ret = njs_value_length(vm, iargs.value, &length);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
@@ -2567,12 +2573,13 @@ njs_array_prototype_reduce_right(njs_vm_
njs_value_t accumulator;
njs_array_iterator_args_t iargs;
- if (njs_is_null_or_undefined(njs_arg(args, nargs, 0))) {
- goto unexpected_args;
+ iargs.value = njs_arg(args, nargs, 0);
+
+ ret = njs_value_to_object(vm, iargs.value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- iargs.value = njs_argument(args, 0);
-
ret = njs_value_length(vm, iargs.value, &iargs.from);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
diff -r c43ebb4722fc -r 3c15734aaeb8 src/njs_value.c
--- a/src/njs_value.c Mon Oct 28 16:10:17 2019 +0300
+++ b/src/njs_value.c Mon Oct 28 16:50:20 2019 +0300
@@ -1171,3 +1171,36 @@ njs_value_property_delete(njs_vm_t *vm,
return NJS_OK;
}
+
+
+njs_int_t
+njs_value_to_object(njs_vm_t *vm, njs_value_t *value)
+{
+ njs_object_t *object;
+
+ if (njs_slow_path(njs_is_null_or_undefined(value))) {
+ njs_type_error(vm, "cannot convert null or undefined to object");
+ return NJS_ERROR;
+ }
+
+ if (njs_is_object(value)) {
+ return NJS_OK;
+
+ }
+
+ if (njs_is_primitive(value)) {
+ object = njs_object_value_alloc(vm, value, value->type);
+ if (njs_slow_path(object == NULL)) {
+ return NJS_ERROR;
+ }
+
+ njs_set_type_object(value, object, njs_object_value_type(value->type));
+
+ return NJS_OK;
+ }
+
+ njs_type_error(vm, "cannot convert %s to object",
+ njs_type_string(value->type));
+
+ return NJS_ERROR;
+}
diff -r c43ebb4722fc -r 3c15734aaeb8 src/njs_value.h
--- a/src/njs_value.h Mon Oct 28 16:10:17 2019 +0300
+++ b/src/njs_value.h Mon Oct 28 16:50:20 2019 +0300
@@ -837,6 +837,7 @@ njs_int_t njs_value_property_set(njs_vm_
njs_value_t *key, njs_value_t *setval);
njs_int_t njs_value_property_delete(njs_vm_t *vm, njs_value_t *value,
njs_value_t *key, njs_value_t *removed);
+njs_int_t njs_value_to_object(njs_vm_t *vm, njs_value_t *value);
#include "njs_number.h"
diff -r c43ebb4722fc -r 3c15734aaeb8 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Mon Oct 28 16:10:17 2019 +0300
+++ b/src/test/njs_unit_test.c Mon Oct 28 16:50:20 2019 +0300
@@ -4026,7 +4026,7 @@ static njs_unit_test_t njs_test[] =
njs_str("") },
{ njs_str("Array.prototype.slice.call(undefined)"),
- njs_str("TypeError: cannot convert undefined to object") },
+ njs_str("TypeError: cannot convert null or undefined to object") },
{ njs_str("Array.prototype.slice.call(1)"),
njs_str("") },
@@ -7741,10 +7741,10 @@ static njs_unit_test_t njs_test[] =
njs_str("1552553") },
{ njs_str("[].join.call()"),
- njs_str("TypeError: cannot convert undefined to object") },
+ njs_str("TypeError: cannot convert null or undefined to object") },
{ njs_str("[].slice.call()"),
- njs_str("TypeError: cannot convert undefined to object") },
+ njs_str("TypeError: cannot convert null or undefined to object") },
{ njs_str("function f(a) {} ; var a = f; var b = f; a === b"),
njs_str("true") },
More information about the nginx-devel
mailing list