[njs] Added implementation of functions: ToInt32, ToUint32, ToLength.

Alexander Borisov alexander.borisov at nginx.com
Mon Apr 15 14:45:49 UTC 2019


details:   https://hg.nginx.org/njs/rev/381086beb15f
branches:  
changeset: 894:381086beb15f
user:      Alexander Borisov <alexander.borisov at nginx.com>
date:      Mon Apr 15 17:23:02 2019 +0300
description:
Added implementation of functions: ToInt32, ToUint32, ToLength.

According to ES6 type conversion: 7.1.5, 7.1.6, and 7.1.15.

diffstat:

 njs/njs_array.c          |   2 +-
 njs/njs_function.c       |   2 +-
 njs/njs_math.c           |   6 ++--
 njs/njs_number.c         |  56 ++++++++++++++++++++++++++++++++++++++++++++++++
 njs/njs_number.h         |   7 +++++-
 njs/njs_string.c         |   2 +-
 njs/njs_vm.c             |  19 +++++++--------
 njs/test/njs_unit_test.c |   2 +-
 8 files changed, 78 insertions(+), 18 deletions(-)

diffs (221 lines):

diff -r f0b5b01a7c55 -r 381086beb15f njs/njs_array.c
--- a/njs/njs_array.c	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/njs_array.c	Mon Apr 15 17:23:02 2019 +0300
@@ -494,7 +494,7 @@ njs_array_prototype_slice_continuation(n
     }
 
     start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
-    length = njs_primitive_value_to_integer(&slice->length);
+    length = njs_primitive_value_to_length(&slice->length);
 
     if (start < 0) {
         start += length;
diff -r f0b5b01a7c55 -r 381086beb15f njs/njs_function.c
--- a/njs/njs_function.c	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/njs_function.c	Mon Apr 15 17:23:02 2019 +0300
@@ -1022,7 +1022,7 @@ njs_function_prototype_apply(njs_vm_t *v
         return NXT_ERROR;
     }
 
-    nargs = njs_primitive_value_to_number(&length);
+    nargs = njs_primitive_value_to_length(&length);
 
     arr = njs_array_alloc(vm, nargs, NJS_ARRAY_SPARE);
     if (nxt_slow_path(arr == NULL)) {
diff -r f0b5b01a7c55 -r 381086beb15f njs/njs_math.c
--- a/njs/njs_math.c	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/njs_math.c	Mon Apr 15 17:23:02 2019 +0300
@@ -227,7 +227,7 @@ njs_object_math_clz32(njs_vm_t *vm, njs_
     uint32_t  ui32;
 
     if (nargs > 1) {
-        ui32 = njs_number_to_integer(args[1].data.u.number);
+        ui32 = njs_number_to_uint32(args[1].data.u.number);
         num = nxt_leading_zeros(ui32);
 
     } else {
@@ -393,8 +393,8 @@ njs_object_math_imul(njs_vm_t *vm, njs_v
     uint32_t  a, b;
 
     if (nargs > 2) {
-        a = njs_number_to_integer(args[1].data.u.number);
-        b = njs_number_to_integer(args[2].data.u.number);
+        a = njs_number_to_uint32(args[1].data.u.number);
+        b = njs_number_to_uint32(args[2].data.u.number);
 
         num = (int32_t) (a * b);
 
diff -r f0b5b01a7c55 -r 381086beb15f njs/njs_number.c
--- a/njs/njs_number.c	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/njs_number.c	Mon Apr 15 17:23:02 2019 +0300
@@ -80,6 +80,27 @@ njs_primitive_value_to_integer(const njs
 }
 
 
+int32_t
+njs_primitive_value_to_int32(const njs_value_t *value)
+{
+    return njs_number_to_int32(njs_primitive_value_to_number(value));
+}
+
+
+uint32_t
+njs_primitive_value_to_uint32(const njs_value_t *value)
+{
+    return njs_number_to_uint32(njs_primitive_value_to_number(value));
+}
+
+
+uint32_t
+njs_primitive_value_to_length(const njs_value_t *value)
+{
+    return njs_number_to_length(njs_primitive_value_to_number(value));
+}
+
+
 double
 njs_number_dec_parse(const u_char **start, const u_char *end)
 {
@@ -822,6 +843,41 @@ njs_number_to_integer(double num)
 }
 
 
+nxt_noinline int32_t
+njs_number_to_int32(double num)
+{
+    return (int32_t) njs_number_to_int64(num);
+}
+
+
+nxt_noinline uint32_t
+njs_number_to_uint32(double num)
+{
+    return (uint32_t) njs_number_to_int64(num);
+}
+
+
+nxt_noinline uint32_t
+njs_number_to_length(double num)
+{
+#if (NXT_NAN_TO_UINT_CONVERSION != 0)
+    if (isnan(num)) {
+        return 0;
+    }
+#endif
+
+    if (num > UINT32_MAX) {
+        return UINT32_MAX;
+
+    } else if (num < 0.0) {
+        return 0;
+    }
+
+    return (uint32_t) (int64_t) num;
+}
+
+
+
 static const njs_object_prop_t  njs_is_nan_function_properties[] =
 {
     /* isNaN.name == "isNaN". */
diff -r f0b5b01a7c55 -r 381086beb15f njs/njs_number.h
--- a/njs/njs_number.h	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/njs_number.h	Mon Apr 15 17:23:02 2019 +0300
@@ -14,6 +14,9 @@
 uint32_t njs_value_to_index(const njs_value_t *value);
 double njs_primitive_value_to_number(const njs_value_t *value);
 int32_t njs_primitive_value_to_integer(const njs_value_t *value);
+int32_t njs_primitive_value_to_int32(const njs_value_t *value);
+uint32_t njs_primitive_value_to_uint32(const njs_value_t *value);
+uint32_t njs_primitive_value_to_length(const njs_value_t *value);
 double njs_number_dec_parse(const u_char **start, const u_char *end);
 uint64_t njs_number_oct_parse(const u_char **start, const u_char *end);
 uint64_t njs_number_bin_parse(const u_char **start, const u_char *end);
@@ -33,7 +36,9 @@ njs_ret_t njs_number_parse_int(njs_vm_t 
 njs_ret_t njs_number_parse_float(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
 nxt_noinline int32_t njs_number_to_integer(double num);
-
+nxt_noinline int32_t njs_number_to_int32(double num);
+nxt_noinline uint32_t njs_number_to_uint32(double num);
+nxt_noinline uint32_t njs_number_to_length(double num);
 
 nxt_inline nxt_int_t
 njs_char_to_hex(u_char c)
diff -r f0b5b01a7c55 -r 381086beb15f njs/njs_string.c
--- a/njs/njs_string.c	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/njs_string.c	Mon Apr 15 17:23:02 2019 +0300
@@ -1445,7 +1445,7 @@ njs_string_bytes_from_array(njs_vm_t *vm
     octet = array->start;
 
     while (length != 0) {
-        *p++ = (u_char) njs_number_to_integer(octet->data.u.number);
+        *p++ = (u_char) njs_number_to_uint32(octet->data.u.number);
         octet++;
         length--;
     }
diff -r f0b5b01a7c55 -r 381086beb15f njs/njs_vm.c
--- a/njs/njs_vm.c	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/njs_vm.c	Mon Apr 15 17:23:02 2019 +0300
@@ -1303,8 +1303,8 @@ njs_vmcode_left_shift(njs_vm_t *vm, njs_
 
     if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
 
-        num1 = njs_number_to_integer(val1->data.u.number);
-        num2 = njs_number_to_integer(val2->data.u.number);
+        num1 = njs_number_to_int32(val1->data.u.number);
+        num2 = njs_number_to_uint32(val2->data.u.number);
         njs_value_number_set(&vm->retval, num1 << (num2 & 0x1f));
 
         return sizeof(njs_vmcode_3addr_t);
@@ -1322,8 +1322,8 @@ njs_vmcode_right_shift(njs_vm_t *vm, njs
 
     if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
 
-        num1 = njs_number_to_integer(val1->data.u.number);
-        num2 = njs_number_to_integer(val2->data.u.number);
+        num1 = njs_number_to_int32(val1->data.u.number);
+        num2 = njs_number_to_uint32(val2->data.u.number);
         njs_value_number_set(&vm->retval, num1 >> (num2 & 0x1f));
 
         return sizeof(njs_vmcode_3addr_t);
@@ -1337,13 +1337,12 @@ njs_ret_t
 njs_vmcode_unsigned_right_shift(njs_vm_t *vm, njs_value_t *val1,
     njs_value_t *val2)
 {
-    int32_t   num2;
-    uint32_t  num1;
+    uint32_t  num1, num2;
 
     if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
 
-        num1 = njs_number_to_integer(val1->data.u.number);
-        num2 = njs_number_to_integer(val2->data.u.number);
+        num1 = njs_number_to_uint32(val1->data.u.number);
+        num2 = njs_number_to_uint32(val2->data.u.number);
         njs_value_number_set(&vm->retval, num1 >> (num2 & 0x1f));
 
         return sizeof(njs_vmcode_3addr_t);
@@ -1462,8 +1461,8 @@ njs_vmcode_bitwise_or(njs_vm_t *vm, njs_
 
     if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
 
-        num1 = njs_number_to_integer(val1->data.u.number);
-        num2 = njs_number_to_integer(val2->data.u.number);
+        num1 = njs_number_to_uint32(val1->data.u.number);
+        num2 = njs_number_to_uint32(val2->data.u.number);
         njs_value_number_set(&vm->retval, num1 | num2);
 
         return sizeof(njs_vmcode_3addr_t);
diff -r f0b5b01a7c55 -r 381086beb15f njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Mon Apr 15 17:23:21 2019 +0300
+++ b/njs/test/njs_unit_test.c	Mon Apr 15 17:23:02 2019 +0300
@@ -3617,7 +3617,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("TypeError: Cannot convert object to primitive value") },
 
     { nxt_string("Array.prototype.slice.call({length:-1})"),
-      nxt_string("MemoryError") },
+      nxt_string("") },
 
     { nxt_string("Array.prototype.slice.call('αβZγ')"),
       nxt_string("α,β,Z,γ") },


More information about the nginx-devel mailing list