]> git.kaiwu.me - njs.git/commitdiff
Added implementation of functions: ToInt32, ToUint32, ToLength.
authorAlexander Borisov <alexander.borisov@nginx.com>
Mon, 15 Apr 2019 14:23:02 +0000 (17:23 +0300)
committerAlexander Borisov <alexander.borisov@nginx.com>
Mon, 15 Apr 2019 14:23:02 +0000 (17:23 +0300)
According to ES6 type conversion: 7.1.5, 7.1.6, and 7.1.15.

njs/njs_array.c
njs/njs_function.c
njs/njs_math.c
njs/njs_number.c
njs/njs_number.h
njs/njs_string.c
njs/njs_vm.c
njs/test/njs_unit_test.c

index 841e43ee3ca5f75186eb00f0b586690ffa3286b3..8ef2114b4bd1e0528e9c3e9f9385bfdd5df84c84 100644 (file)
@@ -494,7 +494,7 @@ njs_array_prototype_slice_continuation(njs_vm_t *vm, njs_value_t *args,
     }
 
     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;
index 0ed7c4aa2ef12284b90958387acb4b7419725c85..cb3f4018a452e7f8b5aa39bccb33892b9f17e39b 100644 (file)
@@ -1022,7 +1022,7 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         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)) {
index 027d0b9ce2623468be556de6110a75e44f8d3755..8e79309dd9f7a9ff4add017b7ce73f0fc54ef012 100644 (file)
@@ -227,7 +227,7 @@ njs_object_math_clz32(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     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_value_t *args, nxt_uint_t nargs,
     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);
 
index 4a1f8b727aa8ab7d4674fbfa603c12af4ce737c1..9bca4c8f5c8bc145f9692a6cdc1c81e98a955e6c 100644 (file)
@@ -80,6 +80,27 @@ njs_primitive_value_to_integer(const njs_value_t *value)
 }
 
 
+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". */
index 767a5a39301ce11dcfa6f32cfcc14eb507ed6178..5e67651b5b07f035e0d05e5f09677b852fad4413 100644 (file)
@@ -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 *vm, njs_value_t *args,
 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)
index 36e95dac82ddaa4715a7a59a64f21fb15c71bb71..579d6afb23c6a49f46f98af542dc89a12db2c290 100644 (file)
@@ -1445,7 +1445,7 @@ njs_string_bytes_from_array(njs_vm_t *vm, const njs_value_t *value)
     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--;
     }
index 7c630461bce59039e0325359d1284a2c3a45b3a1..f4565d01b5d55b92c4f10415799677ea50461c26 100644 (file)
@@ -1303,8 +1303,8 @@ njs_vmcode_left_shift(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
 
     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_value_t *val1, njs_value_t *val2)
 
     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_value_t *val1, njs_value_t *val2)
 
     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);
index fb340ac7d072bcf1bf6280513b0723f3381cac78..b14998cc80c7503fee6b601a6a5a772d115cc37a 100644 (file)
@@ -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,γ") },