From: Alexander Borisov Date: Mon, 15 Apr 2019 14:23:02 +0000 (+0300) Subject: Added implementation of functions: ToInt32, ToUint32, ToLength. X-Git-Tag: 0.3.1~1 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=467e845680e9eb0a5a6ac68cc91509fb35bd8e44;p=njs.git Added implementation of functions: ToInt32, ToUint32, ToLength. According to ES6 type conversion: 7.1.5, 7.1.6, and 7.1.15. --- diff --git a/njs/njs_array.c b/njs/njs_array.c index 841e43ee..8ef2114b 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -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; diff --git a/njs/njs_function.c b/njs/njs_function.c index 0ed7c4aa..cb3f4018 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -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)) { diff --git a/njs/njs_math.c b/njs/njs_math.c index 027d0b9c..8e79309d 100644 --- a/njs/njs_math.c +++ b/njs/njs_math.c @@ -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); diff --git a/njs/njs_number.c b/njs/njs_number.c index 4a1f8b72..9bca4c8f 100644 --- a/njs/njs_number.c +++ b/njs/njs_number.c @@ -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". */ diff --git a/njs/njs_number.h b/njs/njs_number.h index 767a5a39..5e67651b 100644 --- a/njs/njs_number.h +++ b/njs/njs_number.h @@ -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) diff --git a/njs/njs_string.c b/njs/njs_string.c index 36e95dac..579d6afb 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -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--; } diff --git a/njs/njs_vm.c b/njs/njs_vm.c index 7c630461..f4565d01 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -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); diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index fb340ac7..b14998cc 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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,γ") },