From: Alexander Borisov Date: Tue, 22 Oct 2019 16:58:52 +0000 (+0300) Subject: Removed argument prototypes for built-in functions. X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=1d045e0e286ca6b9a44d680254c508095d98f6c9;p=njs.git Removed argument prototypes for built-in functions. Many JS functions do not have fixed prototypes as in C. For example String.prototype.replace() accepts RegExp or String as the first argument. --- diff --git a/src/njs_array.c b/src/njs_array.c index 6f019032..8eb333cb 100644 --- a/src/njs_array.c +++ b/src/njs_array.c @@ -304,7 +304,7 @@ static const njs_object_prop_t njs_array_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isArray"), - .value = njs_native_function(njs_array_is_array, 1, 0), + .value = njs_native_function(njs_array_is_array, 1), .writable = 1, .configurable = 1, }, @@ -314,7 +314,7 @@ static const njs_object_prop_t njs_array_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("of"), - .value = njs_native_function(njs_array_of, 0, 0), + .value = njs_native_function(njs_array_of, 0), .writable = 1, .configurable = 1, }, @@ -423,6 +423,11 @@ njs_array_prototype_slice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, 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; + } + ret = njs_object_length(vm, njs_arg(args, nargs, 0), &object_length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -933,11 +938,17 @@ static njs_int_t njs_array_prototype_splice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + int64_t n, start, length, items, delta, delete; njs_int_t ret; - njs_int_t n, start, length, items, delta, delete; njs_uint_t i; + 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; + } + array = NULL; start = 0; delete = 0; @@ -947,7 +958,17 @@ njs_array_prototype_splice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, length = array->length; if (nargs > 1) { - start = njs_number(&args[1]); + value = njs_argument(args, 1); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &start); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + start = njs_number_to_integer(njs_number(value)); + } if (start < 0) { start += length; @@ -963,7 +984,17 @@ njs_array_prototype_splice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, delete = length - start; if (nargs > 2) { - n = njs_number(&args[2]); + value = njs_argument(args, 2); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + n = njs_number_to_integer(njs_number(value)); + } if (n < 0) { delete = 0; @@ -988,12 +1019,7 @@ njs_array_prototype_splice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, deleted->start[i] = array->start[n]; } - items = nargs - 3; - - if (items < 0) { - items = 0; - } - + items = (nargs > 3) ? nargs - 3: 0; delta = items - delete; if (delta != 0) { @@ -1037,6 +1063,11 @@ njs_array_prototype_reverse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_value_t value; 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; + } + if (njs_is_array(&args[0])) { array = njs_array(&args[0]); length = array->length; @@ -1100,6 +1131,18 @@ njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, 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; + } + + if (nargs > 1 && !njs_is_string(&args[1])) { + ret = njs_value_to_string(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + if (!njs_is_array(&args[0]) || njs_array_len(&args[0]) == 0) { vm->retval = njs_string_empty; return NJS_OK; @@ -2614,7 +2657,6 @@ njs_array_string_sort(njs_vm_t *vm, njs_value_t *args, static const njs_function_t njs_array_string_sort_function = { .object = { .type = NJS_FUNCTION, .shared = 1, .extensible = 1 }, .native = 1, - .args_types = { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_STRING_ARG }, .args_offset = 1, .u.native = njs_array_string_sort, }; @@ -2735,8 +2777,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("slice"), - .value = njs_native_function(njs_array_prototype_slice, 2, - NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_array_prototype_slice, 2), .writable = 1, .configurable = 1, }, @@ -2744,7 +2785,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("push"), - .value = njs_native_function(njs_array_prototype_push, 1, 0), + .value = njs_native_function(njs_array_prototype_push, 1), .writable = 1, .configurable = 1, }, @@ -2752,7 +2793,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("pop"), - .value = njs_native_function(njs_array_prototype_pop, 0, 0), + .value = njs_native_function(njs_array_prototype_pop, 0), .writable = 1, .configurable = 1, }, @@ -2760,7 +2801,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("unshift"), - .value = njs_native_function(njs_array_prototype_unshift, 1, 0), + .value = njs_native_function(njs_array_prototype_unshift, 1), .writable = 1, .configurable = 1, }, @@ -2768,7 +2809,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("shift"), - .value = njs_native_function(njs_array_prototype_shift, 0, 0), + .value = njs_native_function(njs_array_prototype_shift, 0), .writable = 1, .configurable = 1, }, @@ -2776,8 +2817,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("splice"), - .value = njs_native_function(njs_array_prototype_splice, 2, - NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_array_prototype_splice, 2), .writable = 1, .configurable = 1, }, @@ -2785,8 +2825,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("reverse"), - .value = njs_native_function(njs_array_prototype_reverse, 0, - NJS_OBJECT_ARG), + .value = njs_native_function(njs_array_prototype_reverse, 0), .writable = 1, .configurable = 1, }, @@ -2794,7 +2833,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_array_prototype_to_string, 0, 0), + .value = njs_native_function(njs_array_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -2802,8 +2841,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("join"), - .value = njs_native_function(njs_array_prototype_join, 1, - NJS_OBJECT_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_array_prototype_join, 1), .writable = 1, .configurable = 1, }, @@ -2811,7 +2849,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("concat"), - .value = njs_native_function(njs_array_prototype_concat, 1, 0), + .value = njs_native_function(njs_array_prototype_concat, 1), .writable = 1, .configurable = 1, }, @@ -2819,8 +2857,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("indexOf"), - .value = njs_native_function(njs_array_prototype_index_of, 1, - NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_array_prototype_index_of, 1), .writable = 1, .configurable = 1, }, @@ -2828,8 +2865,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("lastIndexOf"), - .value = njs_native_function(njs_array_prototype_last_index_of, 1, - NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_array_prototype_last_index_of, 1), .writable = 1, .configurable = 1, }, @@ -2838,8 +2874,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("includes"), - .value = njs_native_function(njs_array_prototype_includes, 1, - NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_array_prototype_includes, 1), .writable = 1, .configurable = 1, }, @@ -2847,7 +2882,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("forEach"), - .value = njs_native_function(njs_array_prototype_for_each, 1, 0), + .value = njs_native_function(njs_array_prototype_for_each, 1), .writable = 1, .configurable = 1, }, @@ -2855,7 +2890,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("some"), - .value = njs_native_function(njs_array_prototype_some, 1, 0), + .value = njs_native_function(njs_array_prototype_some, 1), .writable = 1, .configurable = 1, }, @@ -2863,7 +2898,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("every"), - .value = njs_native_function(njs_array_prototype_every, 1, 0), + .value = njs_native_function(njs_array_prototype_every, 1), .writable = 1, .configurable = 1, }, @@ -2872,9 +2907,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("fill"), - .value = njs_native_function(njs_array_prototype_fill, 1, - NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG, - NJS_NUMBER_ARG), + .value = njs_native_function(njs_array_prototype_fill, 1), .writable = 1, .configurable = 1, }, @@ -2882,7 +2915,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("filter"), - .value = njs_native_function(njs_array_prototype_filter, 1, 0), + .value = njs_native_function(njs_array_prototype_filter, 1), .writable = 1, .configurable = 1, }, @@ -2891,7 +2924,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("find"), - .value = njs_native_function(njs_array_prototype_find, 1, 0), + .value = njs_native_function(njs_array_prototype_find, 1), .writable = 1, .configurable = 1, }, @@ -2900,7 +2933,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("findIndex"), - .value = njs_native_function(njs_array_prototype_find_index, 1, 0), + .value = njs_native_function(njs_array_prototype_find_index, 1), .writable = 1, .configurable = 1, }, @@ -2908,7 +2941,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("map"), - .value = njs_native_function(njs_array_prototype_map, 1, 0), + .value = njs_native_function(njs_array_prototype_map, 1), .writable = 1, .configurable = 1, }, @@ -2916,7 +2949,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("reduce"), - .value = njs_native_function(njs_array_prototype_reduce, 1, 0), + .value = njs_native_function(njs_array_prototype_reduce, 1), .writable = 1, .configurable = 1, }, @@ -2924,7 +2957,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("reduceRight"), - .value = njs_native_function(njs_array_prototype_reduce_right, 1, 0), + .value = njs_native_function(njs_array_prototype_reduce_right, 1), .writable = 1, .configurable = 1, }, @@ -2932,7 +2965,7 @@ static const njs_object_prop_t njs_array_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("sort"), - .value = njs_native_function(njs_array_prototype_sort, 1, 0), + .value = njs_native_function(njs_array_prototype_sort, 1), .writable = 1, .configurable = 1, }, diff --git a/src/njs_boolean.c b/src/njs_boolean.c index 65139236..79c54bed 100644 --- a/src/njs_boolean.c +++ b/src/njs_boolean.c @@ -145,7 +145,7 @@ static const njs_object_prop_t njs_boolean_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("valueOf"), - .value = njs_native_function(njs_boolean_prototype_value_of, 0, 0), + .value = njs_native_function(njs_boolean_prototype_value_of, 0), .writable = 1, .configurable = 1, }, @@ -153,7 +153,7 @@ static const njs_object_prop_t njs_boolean_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_boolean_prototype_to_string, 0, 0), + .value = njs_native_function(njs_boolean_prototype_to_string, 0), .writable = 1, .configurable = 1, }, diff --git a/src/njs_builtin.c b/src/njs_builtin.c index 8835b03d..6d3438c6 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -11,7 +11,6 @@ typedef struct { njs_function_native_t native; - uint8_t args_types[NJS_ARGS_TYPES_MAX]; } njs_function_init_t; @@ -95,29 +94,25 @@ const njs_object_init_t *njs_constructor_init[] = { const njs_function_init_t njs_native_constructors[] = { /* SunC does not allow empty array initialization. */ - { njs_object_constructor, { 0 } }, - { njs_array_constructor, { 0 } }, - { njs_boolean_constructor, { 0 } }, - { njs_number_constructor, { NJS_SKIP_ARG, NJS_NUMBER_ARG } }, - { njs_string_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_function_constructor, { 0 } }, - { njs_regexp_constructor, { 0 } }, - { njs_date_constructor, { 0 } }, - { njs_hash_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_hmac_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG, - NJS_STRING_ARG } }, - { njs_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_eval_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_internal_error_constructor, - { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_range_error_constructor, - { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_reference_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_syntax_error_constructor, - { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_type_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_uri_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, - { njs_memory_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, + { njs_object_constructor }, + { njs_array_constructor }, + { njs_boolean_constructor }, + { njs_number_constructor }, + { njs_string_constructor }, + { njs_function_constructor}, + { njs_regexp_constructor }, + { njs_date_constructor }, + { njs_hash_constructor }, + { njs_hmac_constructor }, + { njs_error_constructor }, + { njs_eval_error_constructor }, + { njs_internal_error_constructor }, + { njs_range_error_constructor }, + { njs_reference_error_constructor }, + { njs_syntax_error_constructor }, + { njs_type_error_constructor }, + { njs_uri_error_constructor }, + { njs_memory_error_constructor }, }; @@ -331,8 +326,6 @@ njs_builtin_objects_create(njs_vm_t *vm) func->u.native = f->native; - memcpy(func->args_types, f->args_types, NJS_ARGS_TYPES_MAX); - ret = njs_object_hash_init(vm, &func->object.shared_hash, obj); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; @@ -1038,8 +1031,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isFinite"), - .value = njs_native_function(njs_number_is_finite, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_number_global_is_finite, 1), .writable = 1, .configurable = 1, }, @@ -1047,8 +1039,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isNaN"), - .value = njs_native_function(njs_number_global_is_nan, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_number_global_is_nan, 1), .writable = 1, .configurable = 1, }, @@ -1056,8 +1047,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("parseFloat"), - .value = njs_native_function(njs_number_parse_float, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_number_parse_float, 1), .writable = 1, .configurable = 1, }, @@ -1065,8 +1055,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("parseInt"), - .value = njs_native_function(njs_number_parse_int, 2, - NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_number_parse_int, 2), .writable = 1, .configurable = 1, }, @@ -1074,7 +1063,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_object_prototype_to_string, 0, 0), + .value = njs_native_function(njs_object_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -1082,8 +1071,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("encodeURI"), - .value = njs_native_function(njs_string_encode_uri, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_string_encode_uri, 1), .writable = 1, .configurable = 1, }, @@ -1091,8 +1079,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("encodeURIComponent"), - .value = njs_native_function(njs_string_encode_uri_component, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_string_encode_uri_component, 1), .writable = 1, .configurable = 1, }, @@ -1100,8 +1087,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("decodeURI"), - .value = njs_native_function(njs_string_decode_uri, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_string_decode_uri, 1), .writable = 1, .configurable = 1, }, @@ -1109,8 +1095,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("decodeURIComponent"), - .value = njs_native_function(njs_string_decode_uri_component, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_string_decode_uri_component, 1), .writable = 1, .configurable = 1, }, @@ -1118,7 +1103,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("eval"), - .value = njs_native_function(njs_eval_function, 1, 0), + .value = njs_native_function(njs_eval_function, 1), .writable = 1, .configurable = 1, }, @@ -1126,9 +1111,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setTimeout"), - .value = njs_native_function(njs_set_timeout, 2, - NJS_SKIP_ARG, NJS_FUNCTION_ARG, - NJS_NUMBER_ARG), + .value = njs_native_function(njs_set_timeout, 2), .writable = 1, .configurable = 1, }, @@ -1136,8 +1119,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setImmediate"), - .value = njs_native_function(njs_set_immediate, 4, - NJS_SKIP_ARG, NJS_FUNCTION_ARG), + .value = njs_native_function(njs_set_immediate, 4), .writable = 1, .configurable = 1, }, @@ -1145,8 +1127,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("clearTimeout"), - .value = njs_native_function(njs_clear_timeout, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_clear_timeout, 1), .writable = 1, .configurable = 1, }, @@ -1154,8 +1135,7 @@ static const njs_object_prop_t njs_global_this_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("require"), - .value = njs_native_function(njs_module_require, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_module_require, 1), .writable = 1, .configurable = 1, }, @@ -1183,8 +1163,7 @@ static const njs_object_prop_t njs_njs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("dump"), - .value = njs_native_function(njs_dump_value, 0, - NJS_SKIP_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_dump_value, 0), .configurable = 1, }, }; diff --git a/src/njs_crypto.c b/src/njs_crypto.c index 2e79e5e0..1851a27a 100644 --- a/src/njs_crypto.c +++ b/src/njs_crypto.c @@ -323,7 +323,7 @@ static const njs_object_prop_t njs_hash_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_hash_prototype_to_string, 0, 0), + .value = njs_native_function(njs_hash_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -331,8 +331,7 @@ static const njs_object_prop_t njs_hash_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("update"), - .value = njs_native_function(njs_hash_prototype_update, 0, - NJS_OBJECT_ARG, NJS_SKIP_ARG), + .value = njs_native_function(njs_hash_prototype_update, 0), .writable = 1, .configurable = 1, }, @@ -340,8 +339,7 @@ static const njs_object_prop_t njs_hash_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("digest"), - .value = njs_native_function(njs_hash_prototype_digest, 0, - NJS_OBJECT_ARG, NJS_SKIP_ARG), + .value = njs_native_function(njs_hash_prototype_digest, 0), .writable = 1, .configurable = 1, }, @@ -585,7 +583,7 @@ static const njs_object_prop_t njs_hmac_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_hmac_prototype_to_string, 0, 0), + .value = njs_native_function(njs_hmac_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -593,8 +591,7 @@ static const njs_object_prop_t njs_hmac_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("update"), - .value = njs_native_function(njs_hmac_prototype_update, 0, - NJS_OBJECT_ARG, NJS_SKIP_ARG), + .value = njs_native_function(njs_hmac_prototype_update, 0), .writable = 1, .configurable = 1, }, @@ -602,8 +599,7 @@ static const njs_object_prop_t njs_hmac_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("digest"), - .value = njs_native_function(njs_hmac_prototype_digest, 0, - NJS_OBJECT_ARG, NJS_SKIP_ARG), + .value = njs_native_function(njs_hmac_prototype_digest, 0), .writable = 1, .configurable = 1, }, @@ -650,8 +646,7 @@ static const njs_object_prop_t njs_crypto_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("createHash"), - .value = njs_native_function(njs_crypto_create_hash, 0, - NJS_SKIP_ARG), + .value = njs_native_function(njs_crypto_create_hash, 0), .writable = 1, .configurable = 1, }, @@ -659,8 +654,7 @@ static const njs_object_prop_t njs_crypto_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("createHmac"), - .value = njs_native_function(njs_crypto_create_hmac, 0, - NJS_SKIP_ARG), + .value = njs_native_function(njs_crypto_create_hmac, 0), .writable = 1, .configurable = 1, }, diff --git a/src/njs_date.c b/src/njs_date.c index 379ae9c8..8951590f 100644 --- a/src/njs_date.c +++ b/src/njs_date.c @@ -389,9 +389,17 @@ static njs_int_t njs_date_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double time; + double time; + njs_int_t ret; if (nargs > 1) { + if (njs_slow_path(!njs_is_string(&args[1]))) { + ret = njs_value_to_string(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + time = njs_date_string_parse(&args[1]); } else { @@ -1016,7 +1024,7 @@ static const njs_object_prop_t njs_date_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("UTC"), - .value = njs_native_function(njs_date_utc, 7, 0), + .value = njs_native_function(njs_date_utc, 7), .writable = 1, .configurable = 1, }, @@ -1024,7 +1032,7 @@ static const njs_object_prop_t njs_date_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("now"), - .value = njs_native_function(njs_date_now, 0, 0), + .value = njs_native_function(njs_date_now, 0), .writable = 1, .configurable = 1, }, @@ -1032,8 +1040,7 @@ static const njs_object_prop_t njs_date_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("parse"), - .value = njs_native_function(njs_date_parse, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_date_parse, 1), .writable = 1, .configurable = 1, }, @@ -1051,6 +1058,13 @@ static njs_int_t njs_date_prototype_value_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + njs_set_number(&vm->retval, njs_date(&args[0])->time); return NJS_OK; @@ -1061,6 +1075,13 @@ static njs_int_t njs_date_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + return njs_date_string(vm, "%a %b %d %Y %T GMT%z (%Z)", njs_date(&args[0])->time); } @@ -1070,6 +1091,13 @@ static njs_int_t njs_date_prototype_to_date_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + return njs_date_string(vm, "%a %b %d %Y", njs_date(&args[0])->time); } @@ -1078,6 +1106,13 @@ static njs_int_t njs_date_prototype_to_time_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + return njs_date_string(vm, "%T GMT%z (%Z)", njs_date(&args[0])->time); } @@ -1120,6 +1155,13 @@ njs_date_prototype_to_utc_string(njs_vm_t *vm, njs_value_t *args, static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (!isnan(time)) { @@ -1144,6 +1186,13 @@ static njs_int_t njs_date_prototype_to_iso_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + return njs_date_to_string(vm, &vm->retval, &args[0]); } @@ -1189,6 +1238,13 @@ njs_date_prototype_get_full_year(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1212,6 +1268,13 @@ njs_date_prototype_get_utc_full_year(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1235,6 +1298,13 @@ njs_date_prototype_get_month(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1258,6 +1328,13 @@ njs_date_prototype_get_utc_month(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1282,6 +1359,13 @@ njs_date_prototype_get_date(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1305,6 +1389,13 @@ njs_date_prototype_get_utc_date(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1328,6 +1419,13 @@ njs_date_prototype_get_day(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1351,6 +1449,13 @@ njs_date_prototype_get_utc_day(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1374,6 +1479,13 @@ njs_date_prototype_get_hours(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1398,6 +1510,13 @@ njs_date_prototype_get_utc_hours(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1421,6 +1540,13 @@ njs_date_prototype_get_minutes(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1445,6 +1571,13 @@ njs_date_prototype_get_utc_minutes(njs_vm_t *vm, njs_value_t *args, time_t clock; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1466,6 +1599,13 @@ njs_date_prototype_get_seconds(njs_vm_t *vm, njs_value_t *args, { double value; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1484,6 +1624,13 @@ njs_date_prototype_get_milliseconds(njs_vm_t *vm, njs_value_t *args, { double value; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1502,6 +1649,13 @@ njs_date_prototype_get_timezone_offset(njs_vm_t *vm, njs_value_t *args, { double value; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + value = njs_date(&args[0])->time; if (njs_fast_path(!isnan(value))) { @@ -1518,9 +1672,24 @@ static njs_int_t njs_date_prototype_set_time(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double time; + double time; + njs_int_t ret; + + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + time = njs_timeclip(njs_number(&args[1])); } else { @@ -1538,13 +1707,28 @@ static njs_int_t njs_date_prototype_set_milliseconds(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double time; + double time; + njs_int_t ret; + + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + time = (int64_t) (time / 1000) * 1000 + njs_number(&args[1]); } else { @@ -1563,16 +1747,44 @@ static njs_int_t njs_date_prototype_set_seconds(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double time; - int64_t sec, ms; + double time; + int64_t sec, ms; + njs_int_t ret; + + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + ms = njs_number(&args[2]); + + } else { + ms = (int64_t) time % 1000; + } + sec = njs_number(&args[1]); - ms = (nargs > 2) ? njs_number(&args[2]) : (int64_t) time % 1000; time = (int64_t) (time / 60000) * 60000 + sec * 1000 + ms; @@ -1595,23 +1807,57 @@ njs_date_prototype_set_minutes(njs_vm_t *vm, njs_value_t *args, double time; time_t clock; int64_t ms; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; localtime_r(&clock, &tm); tm.tm_min = njs_number(&args[1]); if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_sec = njs_number(&args[2]); } - ms = (nargs > 3) ? njs_number(&args[3]) : (int64_t) time % 1000; + if (nargs > 3) { + if (njs_slow_path(!njs_is_number(&args[3]))) { + ret = njs_value_to_numeric(vm, &args[3], &args[3]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + ms = njs_number(&args[3]); + + } else { + ms = (int64_t) time % 1000; + } time = njs_date_time(&tm, ms); @@ -1631,22 +1877,61 @@ static njs_int_t njs_date_prototype_set_utc_minutes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double time; - int64_t clock, min, sec, ms; + double time; + int64_t clock, min, sec, ms; + njs_int_t ret; + + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { - clock = time / 1000; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } - sec = (nargs > 2) ? njs_number(&args[2]) : clock % 60; + clock = time / 1000; min = njs_number(&args[1]); + if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + sec = njs_number(&args[2]); + + } else { + sec = clock % 60; + } + clock = clock / 3600 * 3600 + min * 60 + sec; - ms = (nargs > 3) ? njs_number(&args[3]) : (int64_t) time % 1000; + if (nargs > 3) { + if (njs_slow_path(!njs_is_number(&args[3]))) { + ret = njs_value_to_numeric(vm, &args[3], &args[3]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + ms = njs_number(&args[3]); + + } else { + ms = (int64_t) time % 1000; + } time = clock * 1000 + ms; @@ -1669,27 +1954,68 @@ njs_date_prototype_set_hours(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, double time; time_t clock; int64_t ms; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; localtime_r(&clock, &tm); tm.tm_hour = njs_number(&args[1]); if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_min = njs_number(&args[2]); } if (nargs > 3) { + if (njs_slow_path(!njs_is_number(&args[3]))) { + ret = njs_value_to_numeric(vm, &args[3], &args[3]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_sec = njs_number(&args[3]); } - ms = (nargs > 4) ? njs_number(&args[4]) : (int64_t) time % 1000; + if (nargs > 4) { + if (njs_slow_path(!njs_is_number(&args[4]))) { + ret = njs_value_to_numeric(vm, &args[4], &args[4]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + ms = njs_number(&args[4]); + + } else { + ms = (int64_t) time % 1000; + } time = njs_date_time(&tm, ms); @@ -1709,24 +2035,76 @@ static njs_int_t njs_date_prototype_set_utc_hours(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double time; - int64_t clock, hour, min, sec, ms; + double time; + int64_t clock, hour, min, sec, ms; + njs_int_t ret; + + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; - sec = (nargs > 3) ? njs_number(&args[3]) : clock % 60; - min = (nargs > 2) ? njs_number(&args[2]) : clock / 60 % 60; hour = njs_number(&args[1]); - clock = clock / 86400 * 86400 + hour * 3600 + min * 60 + sec; + if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + min = njs_number(&args[2]); + + } else { + min = clock / 60 % 60; + } - ms = (nargs > 4) ? njs_number(&args[4]) : (int64_t) time % 1000; + if (nargs > 3) { + if (njs_slow_path(!njs_is_number(&args[3]))) { + ret = njs_value_to_numeric(vm, &args[3], &args[3]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + sec = njs_number(&args[3]); + + } else { + sec = clock % 60; + } + + if (nargs > 4) { + if (njs_slow_path(!njs_is_number(&args[4]))) { + ret = njs_value_to_numeric(vm, &args[4], &args[4]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + ms = njs_number(&args[4]); + + } else { + ms = (int64_t) time % 1000; + } + clock = clock / 86400 * 86400 + hour * 3600 + min * 60 + sec; time = clock * 1000 + ms; } else { @@ -1747,13 +2125,28 @@ njs_date_prototype_set_date(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, { double time; time_t clock; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; localtime_r(&clock, &tm); @@ -1779,13 +2172,28 @@ njs_date_prototype_set_utc_date(njs_vm_t *vm, njs_value_t *args, { double time; time_t clock; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; gmtime_r(&clock, &tm); @@ -1811,19 +2219,41 @@ njs_date_prototype_set_month(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, { double time; time_t clock; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; localtime_r(&clock, &tm); tm.tm_mon = njs_number(&args[1]); if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_mday = njs_number(&args[2]); } @@ -1847,19 +2277,41 @@ njs_date_prototype_set_utc_month(njs_vm_t *vm, njs_value_t *args, { double time; time_t clock; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; gmtime_r(&clock, &tm); tm.tm_mon = njs_number(&args[1]); if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_mday = njs_number(&args[2]); } @@ -1883,23 +2335,52 @@ njs_date_prototype_set_full_year(njs_vm_t *vm, njs_value_t *args, { double time; time_t clock; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; localtime_r(&clock, &tm); tm.tm_year = njs_number(&args[1]) - 1900; if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_mon = njs_number(&args[2]); } if (nargs > 3) { + if (njs_slow_path(!njs_is_number(&args[3]))) { + ret = njs_value_to_numeric(vm, &args[3], &args[3]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_mday = njs_number(&args[3]); } @@ -1923,23 +2404,52 @@ njs_date_prototype_set_utc_full_year(njs_vm_t *vm, njs_value_t *args, { double time; time_t clock; + njs_int_t ret; struct tm tm; + if (njs_slow_path(!njs_is_date(&args[0]))) { + njs_type_error(vm, "cannot convert %s to date", + njs_type_string(args[0].type)); + + return NJS_ERROR; + } + time = njs_date(&args[0])->time; if (njs_fast_path(!isnan(time))) { if (nargs > 1) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + clock = time / 1000; gmtime_r(&clock, &tm); tm.tm_year = njs_number(&args[1]) - 1900; if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_mon = njs_number(&args[2]); } if (nargs > 3) { + if (njs_slow_path(!njs_is_number(&args[3]))) { + ret = njs_value_to_numeric(vm, &args[3], &args[3]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + tm.tm_mday = njs_number(&args[3]); } @@ -2034,8 +2544,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("valueOf"), - .value = njs_native_function(njs_date_prototype_value_of, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_value_of, 0), .writable = 1, .configurable = 1, }, @@ -2043,8 +2552,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_date_prototype_to_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -2052,8 +2560,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toDateString"), - .value = njs_native_function(njs_date_prototype_to_date_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_date_string, 0), .writable = 1, .configurable = 1, }, @@ -2061,8 +2568,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toTimeString"), - .value = njs_native_function(njs_date_prototype_to_time_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_time_string, 0), .writable = 1, .configurable = 1, }, @@ -2070,8 +2576,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toLocaleString"), - .value = njs_native_function(njs_date_prototype_to_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -2079,8 +2584,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("toLocaleDateString"), - .value = njs_native_function(njs_date_prototype_to_date_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_date_string, 0), .writable = 1, .configurable = 1, }, @@ -2088,8 +2592,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("toLocaleTimeString"), - .value = njs_native_function(njs_date_prototype_to_time_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_time_string, 0), .writable = 1, .configurable = 1, }, @@ -2097,8 +2600,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toUTCString"), - .value = njs_native_function(njs_date_prototype_to_utc_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_utc_string, 0), .writable = 1, .configurable = 1, }, @@ -2106,8 +2608,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toISOString"), - .value = njs_native_function(njs_date_prototype_to_iso_string, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_to_iso_string, 0), .writable = 1, .configurable = 1, }, @@ -2115,8 +2616,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getTime"), - .value = njs_native_function(njs_date_prototype_value_of, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_value_of, 0), .writable = 1, .configurable = 1, }, @@ -2124,8 +2624,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getFullYear"), - .value = njs_native_function(njs_date_prototype_get_full_year, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_full_year, 0), .writable = 1, .configurable = 1, }, @@ -2133,8 +2632,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getUTCFullYear"), - .value = njs_native_function(njs_date_prototype_get_utc_full_year, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_utc_full_year, 0), .writable = 1, .configurable = 1, }, @@ -2142,8 +2640,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getMonth"), - .value = njs_native_function(njs_date_prototype_get_month, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_month, 0), .writable = 1, .configurable = 1, }, @@ -2151,8 +2648,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getUTCMonth"), - .value = njs_native_function(njs_date_prototype_get_utc_month, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_utc_month, 0), .writable = 1, .configurable = 1, }, @@ -2160,8 +2656,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getDate"), - .value = njs_native_function(njs_date_prototype_get_date, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_date, 0), .writable = 1, .configurable = 1, }, @@ -2169,8 +2664,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getUTCDate"), - .value = njs_native_function(njs_date_prototype_get_utc_date, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_utc_date, 0), .writable = 1, .configurable = 1, }, @@ -2178,8 +2672,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getDay"), - .value = njs_native_function(njs_date_prototype_get_day, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_day, 0), .writable = 1, .configurable = 1, }, @@ -2187,8 +2680,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getUTCDay"), - .value = njs_native_function(njs_date_prototype_get_utc_day, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_utc_day, 0), .writable = 1, .configurable = 1, }, @@ -2196,8 +2688,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getHours"), - .value = njs_native_function(njs_date_prototype_get_hours, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_hours, 0), .writable = 1, .configurable = 1, }, @@ -2205,8 +2696,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getUTCHours"), - .value = njs_native_function(njs_date_prototype_get_utc_hours, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_utc_hours, 0), .writable = 1, .configurable = 1, }, @@ -2214,8 +2704,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getMinutes"), - .value = njs_native_function(njs_date_prototype_get_minutes, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_minutes, 0), .writable = 1, .configurable = 1, }, @@ -2223,8 +2712,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getUTCMinutes"), - .value = njs_native_function(njs_date_prototype_get_utc_minutes, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_utc_minutes, 0), .writable = 1, .configurable = 1, }, @@ -2232,8 +2720,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getSeconds"), - .value = njs_native_function(njs_date_prototype_get_seconds, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_seconds, 0), .writable = 1, .configurable = 1, }, @@ -2241,8 +2728,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getUTCSeconds"), - .value = njs_native_function(njs_date_prototype_get_seconds, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_seconds, 0), .writable = 1, .configurable = 1, }, @@ -2250,8 +2736,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("getMilliseconds"), - .value = njs_native_function(njs_date_prototype_get_milliseconds, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_milliseconds, 0), .writable = 1, .configurable = 1, }, @@ -2259,8 +2744,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("getUTCMilliseconds"), - .value = njs_native_function(njs_date_prototype_get_milliseconds, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_milliseconds, 0), .writable = 1, .configurable = 1, }, @@ -2268,8 +2752,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("getTimezoneOffset"), - .value = njs_native_function(njs_date_prototype_get_timezone_offset, 0, - NJS_DATE_ARG), + .value = njs_native_function(njs_date_prototype_get_timezone_offset, 0), .writable = 1, .configurable = 1, }, @@ -2277,8 +2760,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setTime"), - .value = njs_native_function(njs_date_prototype_set_time, 1, - NJS_DATE_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_time, 1), .writable = 1, .configurable = 1, }, @@ -2286,8 +2768,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("setMilliseconds"), - .value = njs_native_function(njs_date_prototype_set_milliseconds, 1, - NJS_DATE_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_milliseconds, 1), .writable = 1, .configurable = 1, }, @@ -2295,8 +2776,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("setUTCMilliseconds"), - .value = njs_native_function(njs_date_prototype_set_milliseconds, 1, - NJS_DATE_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_milliseconds, 1), .writable = 1, .configurable = 1, }, @@ -2304,8 +2784,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setSeconds"), - .value = njs_native_function(njs_date_prototype_set_seconds, 2, - NJS_DATE_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_seconds, 2), .writable = 1, .configurable = 1, }, @@ -2313,8 +2792,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setUTCSeconds"), - .value = njs_native_function(njs_date_prototype_set_seconds, 2, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_seconds, 2), .writable = 1, .configurable = 1, }, @@ -2322,9 +2800,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setMinutes"), - .value = njs_native_function(njs_date_prototype_set_minutes, 3, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, - NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_minutes, 3), .writable = 1, .configurable = 1, }, @@ -2332,9 +2808,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setUTCMinutes"), - .value = njs_native_function(njs_date_prototype_set_utc_minutes, 3, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, - NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_utc_minutes, 3), .writable = 1, .configurable = 1, }, @@ -2342,9 +2816,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setHours"), - .value = njs_native_function(njs_date_prototype_set_hours, 4, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, - NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_hours, 4), .writable = 1, .configurable = 1, }, @@ -2352,9 +2824,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setUTCHours"), - .value = njs_native_function(njs_date_prototype_set_utc_hours, 4, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, - NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_utc_hours, 4), .writable = 1, .configurable = 1, }, @@ -2362,8 +2832,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setDate"), - .value = njs_native_function(njs_date_prototype_set_date, 1, - NJS_DATE_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_date, 1), .writable = 1, .configurable = 1, }, @@ -2371,8 +2840,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setUTCDate"), - .value = njs_native_function(njs_date_prototype_set_utc_date, 1, - NJS_DATE_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_utc_date, 1), .writable = 1, .configurable = 1, }, @@ -2380,8 +2848,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setMonth"), - .value = njs_native_function(njs_date_prototype_set_month, 2, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_month, 2), .writable = 1, .configurable = 1, }, @@ -2389,8 +2856,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setUTCMonth"), - .value = njs_native_function(njs_date_prototype_set_utc_month, 2, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_utc_month, 2), .writable = 1, .configurable = 1, }, @@ -2398,9 +2864,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setFullYear"), - .value = njs_native_function(njs_date_prototype_set_full_year, 3, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, - NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_full_year, 3), .writable = 1, .configurable = 1, }, @@ -2408,9 +2872,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("setUTCFullYear"), - .value = njs_native_function(njs_date_prototype_set_utc_full_year, 3, - NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, - NJS_NUMBER_ARG), + .value = njs_native_function(njs_date_prototype_set_utc_full_year, 3), .writable = 1, .configurable = 1, }, @@ -2418,7 +2880,7 @@ static const njs_object_prop_t njs_date_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toJSON"), - .value = njs_native_function(njs_date_prototype_to_json, 1, 0), + .value = njs_native_function(njs_date_prototype_to_json, 1), .writable = 1, .configurable = 1, }, diff --git a/src/njs_error.c b/src/njs_error.c index 6ca7b11f..682be041 100644 --- a/src/njs_error.c +++ b/src/njs_error.c @@ -137,11 +137,21 @@ static njs_int_t njs_error_create(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_value_type_t type) { - njs_object_t *error; - const njs_value_t *value; + njs_int_t ret; + njs_value_t *value; + njs_object_t *error; value = njs_arg(args, nargs, 1); + if (njs_slow_path(!njs_is_string(value))) { + if (!njs_is_undefined(value)) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + } + error = njs_error_alloc(vm, type, NULL, njs_is_defined(value) ? value : NULL); if (njs_slow_path(error == NULL)) { @@ -734,7 +744,7 @@ static const njs_object_prop_t njs_error_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("valueOf"), - .value = njs_native_function(njs_error_prototype_value_of, 0, 0), + .value = njs_native_function(njs_error_prototype_value_of, 0), .writable = 1, .configurable = 1, }, @@ -742,7 +752,7 @@ static const njs_object_prop_t njs_error_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_error_prototype_to_string, 0, 0), + .value = njs_native_function(njs_error_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -816,8 +826,7 @@ static const njs_object_prop_t njs_internal_error_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_internal_error_prototype_to_string, - 0, 0), + .value = njs_native_function(njs_internal_error_prototype_to_string, 0), .writable = 1, .configurable = 1, }, diff --git a/src/njs_fs.c b/src/njs_fs.c index 3256b318..9d89df32 100644 --- a/src/njs_fs.c +++ b/src/njs_fs.c @@ -896,25 +896,43 @@ static njs_int_t njs_fs_rename_sync(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int ret; - const char *old_path, *new_path; + int ret; + const char *old_path, *new_path; + njs_value_t *old, *new; - if (njs_slow_path(!njs_is_string(njs_arg(args, nargs, 1)))) { - njs_type_error(vm, "oldPath must be a string"); - return NJS_ERROR; - } + if (njs_slow_path(nargs < 3)) { + if (nargs < 2) { + njs_type_error(vm, "oldPath must be a string"); + return NJS_ERROR; + } - if (njs_slow_path(!njs_is_string(njs_arg(args, nargs, 2)))) { njs_type_error(vm, "newPath must be a string"); return NJS_ERROR; } - old_path = njs_string_to_c_string(vm, njs_argument(args, 1)); + old = njs_argument(args, 1); + new = njs_argument(args, 2); + + if (njs_slow_path(!njs_is_string(old))) { + ret = njs_value_to_string(vm, old, old); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + if (njs_slow_path(!njs_is_string(new))) { + ret = njs_value_to_string(vm, new, new); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + old_path = njs_string_to_c_string(vm, old); if (njs_slow_path(old_path == NULL)) { return NJS_ERROR; } - new_path = njs_string_to_c_string(vm, njs_argument(args, 2)); + new_path = njs_string_to_c_string(vm, new); if (njs_slow_path(new_path == NULL)) { return NJS_ERROR; } @@ -1140,7 +1158,7 @@ static const njs_object_prop_t njs_fs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("readFile"), - .value = njs_native_function(njs_fs_read_file, 0, 0), + .value = njs_native_function(njs_fs_read_file, 0), .writable = 1, .configurable = 1, }, @@ -1148,7 +1166,7 @@ static const njs_object_prop_t njs_fs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("readFileSync"), - .value = njs_native_function(njs_fs_read_file_sync, 0, 0), + .value = njs_native_function(njs_fs_read_file_sync, 0), .writable = 1, .configurable = 1, }, @@ -1156,7 +1174,7 @@ static const njs_object_prop_t njs_fs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("appendFile"), - .value = njs_native_function(njs_fs_append_file, 0, 0), + .value = njs_native_function(njs_fs_append_file, 0), .writable = 1, .configurable = 1, }, @@ -1164,7 +1182,7 @@ static const njs_object_prop_t njs_fs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("appendFileSync"), - .value = njs_native_function(njs_fs_append_file_sync, 0, 0), + .value = njs_native_function(njs_fs_append_file_sync, 0), .writable = 1, .configurable = 1, }, @@ -1172,7 +1190,7 @@ static const njs_object_prop_t njs_fs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("writeFile"), - .value = njs_native_function(njs_fs_write_file, 0, 0), + .value = njs_native_function(njs_fs_write_file, 0), .writable = 1, .configurable = 1, }, @@ -1180,7 +1198,7 @@ static const njs_object_prop_t njs_fs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("writeFileSync"), - .value = njs_native_function(njs_fs_write_file_sync, 0, 0), + .value = njs_native_function(njs_fs_write_file_sync, 0), .writable = 1, .configurable = 1, }, @@ -1188,8 +1206,7 @@ static const njs_object_prop_t njs_fs_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("renameSync"), - .value = njs_native_function(njs_fs_rename_sync, 0, NJS_STRING_ARG, - NJS_STRING_ARG, 0), + .value = njs_native_function(njs_fs_rename_sync, 0), .writable = 1, .configurable = 1, }, diff --git a/src/njs_function.c b/src/njs_function.c index 3bca2890..c59189c8 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -11,8 +11,6 @@ static njs_function_t *njs_function_copy(njs_vm_t *vm, njs_function_t *function); static njs_native_frame_t *njs_function_frame_alloc(njs_vm_t *vm, size_t size); -static njs_int_t njs_normalize_args(njs_vm_t *vm, njs_value_t *args, - uint8_t *args_types, njs_uint_t nargs); njs_function_t * @@ -269,8 +267,8 @@ const njs_object_prop_t njs_arguments_object_instance_properties[] = .type = NJS_PROPERTY, .name = njs_string("callee"), .value = njs_value(NJS_INVALID, 1, NAN), - .getter = njs_native_function(njs_function_prototype_thrower, 0, 0), - .setter = njs_native_function(njs_function_prototype_thrower, 0, 0), + .getter = njs_native_function(njs_function_prototype_thrower, 0), + .setter = njs_native_function(njs_function_prototype_thrower, 0), .writable = NJS_ATTRIBUTE_UNSET, }, }; @@ -586,12 +584,6 @@ njs_function_native_call(njs_vm_t *vm) frame = (njs_frame_t *) native; function = native->function; - ret = njs_normalize_args(vm, native->arguments, function->args_types, - native->nargs); - if (ret != NJS_OK) { - return ret; - } - ret = function->u.native(vm, native->arguments, native->nargs, frame->retval); @@ -622,142 +614,6 @@ njs_function_native_call(njs_vm_t *vm) } -static njs_int_t -njs_normalize_args(njs_vm_t *vm, njs_value_t *args, uint8_t *args_types, - njs_uint_t nargs) -{ - njs_int_t ret; - njs_uint_t n; - - n = njs_min(nargs, NJS_ARGS_TYPES_MAX); - - while (n != 0) { - - switch (*args_types) { - - case NJS_STRING_OBJECT_ARG: - - if (njs_is_null_or_undefined(args)) { - goto type_error; - } - - /* Fall through. */ - - case NJS_STRING_ARG: - - if (!njs_is_string(args)) { - ret = njs_value_to_string(vm, args, args); - if (ret != NJS_OK) { - return ret; - } - } - - break; - - case NJS_NUMBER_ARG: - - if (!njs_is_numeric(args)) { - ret = njs_value_to_numeric(vm, args, args); - if (ret != NJS_OK) { - return ret; - } - } - - break; - - case NJS_INTEGER_ARG: - - if (!njs_is_numeric(args)) { - ret = njs_value_to_numeric(vm, args, args); - if (ret != NJS_OK) { - return ret; - } - } - - /* Numbers are truncated to fit in 32-bit integers. */ - - if (!isnan(njs_number(args))) { - if (njs_number(args) > 2147483647.0) { - njs_number(args) = 2147483647.0; - - } else if (njs_number(args) < -2147483648.0) { - njs_number(args) = -2147483648.0; - } - } - - break; - - case NJS_FUNCTION_ARG: - - switch (args->type) { - case NJS_STRING: - case NJS_FUNCTION: - break; - - default: - ret = njs_value_to_string(vm, args, args); - if (ret != NJS_OK) { - return ret; - } - } - - break; - - case NJS_REGEXP_ARG: - - switch (args->type) { - case NJS_UNDEFINED: - case NJS_STRING: - case NJS_REGEXP: - break; - - default: - ret = njs_value_to_string(vm, args, args); - if (ret != NJS_OK) { - return ret; - } - } - - break; - - case NJS_DATE_ARG: - if (!njs_is_date(args)) { - goto type_error; - } - - break; - - case NJS_OBJECT_ARG: - - if (njs_is_null_or_undefined(args)) { - goto type_error; - } - - break; - - case NJS_SKIP_ARG: - break; - - case 0: - return NJS_OK; - } - - args++; - args_types++; - n--; - } - - return NJS_OK; - -type_error: - - njs_type_error(vm, "cannot convert %s to %s", njs_type_string(args->type), - njs_arg_type_string(*args_types)); - - return NJS_ERROR; -} - - void njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *native) { @@ -1257,7 +1113,7 @@ static const njs_object_prop_t njs_function_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("call"), - .value = njs_native_function(njs_function_prototype_call, 1, 0), + .value = njs_native_function(njs_function_prototype_call, 1), .writable = 1, .configurable = 1, }, @@ -1265,7 +1121,7 @@ static const njs_object_prop_t njs_function_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("apply"), - .value = njs_native_function(njs_function_prototype_apply, 2, 0), + .value = njs_native_function(njs_function_prototype_apply, 2), .writable = 1, .configurable = 1, }, @@ -1273,7 +1129,7 @@ static const njs_object_prop_t njs_function_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("bind"), - .value = njs_native_function(njs_function_prototype_bind, 1, 0), + .value = njs_native_function(njs_function_prototype_bind, 1), .writable = 1, .configurable = 1, }, @@ -1282,8 +1138,8 @@ static const njs_object_prop_t njs_function_prototype_properties[] = .type = NJS_PROPERTY, .name = njs_string("caller"), .value = njs_value(NJS_INVALID, 1, NAN), - .getter = njs_native_function(njs_function_prototype_thrower, 0, 0), - .setter = njs_native_function(njs_function_prototype_thrower, 0, 0), + .getter = njs_native_function(njs_function_prototype_thrower, 0), + .setter = njs_native_function(njs_function_prototype_thrower, 0), .writable = NJS_ATTRIBUTE_UNSET, .configurable = 1, }, @@ -1292,8 +1148,8 @@ static const njs_object_prop_t njs_function_prototype_properties[] = .type = NJS_PROPERTY, .name = njs_string("arguments"), .value = njs_value(NJS_INVALID, 1, NAN), - .getter = njs_native_function(njs_function_prototype_thrower, 0, 0), - .setter = njs_native_function(njs_function_prototype_thrower, 0, 0), + .getter = njs_native_function(njs_function_prototype_thrower, 0), + .setter = njs_native_function(njs_function_prototype_thrower, 0), .writable = NJS_ATTRIBUTE_UNSET, .configurable = 1, }, diff --git a/src/njs_function.h b/src/njs_function.h index 29decd01..efaffc81 100644 --- a/src/njs_function.h +++ b/src/njs_function.h @@ -8,17 +8,6 @@ #define _NJS_FUNCTION_H_INCLUDED_ -#define NJS_SKIP_ARG 1 -#define NJS_NUMBER_ARG 2 -#define NJS_INTEGER_ARG 3 -#define NJS_STRING_ARG 4 -#define NJS_OBJECT_ARG 5 -#define NJS_STRING_OBJECT_ARG 6 -#define NJS_FUNCTION_ARG 7 -#define NJS_REGEXP_ARG 8 -#define NJS_DATE_ARG 9 - - struct njs_function_lambda_s { uint32_t nargs; uint32_t local_size; diff --git a/src/njs_json.c b/src/njs_json.c index feeeb407..45e24db4 100644 --- a/src/njs_json.c +++ b/src/njs_json.c @@ -146,10 +146,11 @@ static njs_int_t njs_json_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_value_t *value, *wrapper; - const njs_value_t *text, *reviver; + njs_int_t ret; + njs_value_t *text, *value, *wrapper; const u_char *p, *end; njs_json_parse_t *parse, json_parse; + const njs_value_t *reviver; njs_string_prop_t string; njs_json_parse_ctx_t ctx; @@ -163,8 +164,16 @@ njs_json_parse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, text = njs_arg(args, nargs, 1); - if (njs_is_undefined(text)) { - text = &njs_string_undefined; + if (njs_slow_path(!njs_is_string(text))) { + if (njs_is_undefined(text)) { + text = njs_value_arg(&njs_string_undefined); + + } else { + ret = njs_value_to_string(vm, text, text); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } } (void) njs_string_prop(&string, text); @@ -2101,9 +2110,7 @@ static const njs_object_prop_t njs_json_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("parse"), - .value = njs_native_function(njs_json_parse, 2, - NJS_SKIP_ARG, NJS_STRING_ARG, - NJS_OBJECT_ARG), + .value = njs_native_function(njs_json_parse, 2), .writable = 1, .configurable = 1, }, @@ -2112,9 +2119,7 @@ static const njs_object_prop_t njs_json_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("stringify"), - .value = njs_native_function(njs_json_stringify, 3, - NJS_SKIP_ARG, NJS_SKIP_ARG, NJS_SKIP_ARG, - NJS_SKIP_ARG), + .value = njs_native_function(njs_json_stringify, 3), .writable = 1, .configurable = 1, }, diff --git a/src/njs_math.c b/src/njs_math.c index 48306e3e..ab4393db 100644 --- a/src/njs_math.c +++ b/src/njs_math.c @@ -12,16 +12,21 @@ static njs_int_t njs_object_math_abs(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = fabs(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, fabs(njs_number(&args[1]))); return NJS_OK; } @@ -31,25 +36,31 @@ static njs_int_t njs_object_math_acos(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + double num; + njs_int_t ret; - if (nargs > 1) { - num = njs_number(&args[1]); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } -#if (NJS_SOLARIS) - /* On Solaris acos(x) returns 0 for x > 1. */ - if (fabs(num) > 1.0) { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } -#endif + } - num = acos(num); + num = njs_number(&args[1]); - } else { +#if (NJS_SOLARIS) + /* On Solaris acos(x) returns 0 for x > 1. */ + if (fabs(num) > 1.0) { num = NAN; } +#endif - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, acos(num)); return NJS_OK; } @@ -59,16 +70,21 @@ static njs_int_t njs_object_math_acosh(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = acosh(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, acosh(njs_number(&args[1]))); return NJS_OK; } @@ -78,25 +94,31 @@ static njs_int_t njs_object_math_asin(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + double num; + njs_int_t ret; - if (nargs > 1) { - num = njs_number(&args[1]); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } -#if (NJS_SOLARIS) - /* On Solaris asin(x) returns 0 for x > 1. */ - if (fabs(num) > 1.0) { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } -#endif + } - num = asin(num); + num = njs_number(&args[1]); - } else { +#if (NJS_SOLARIS) + /* On Solaris asin(x) returns 0 for x > 1. */ + if (fabs(num) > 1.0) { num = NAN; } +#endif - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, asin(num)); return NJS_OK; } @@ -106,16 +128,21 @@ static njs_int_t njs_object_math_asinh(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = asinh(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, asinh(njs_number(&args[1]))); return NJS_OK; } @@ -125,16 +152,21 @@ static njs_int_t njs_object_math_atan(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = atan(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, atan(njs_number(&args[1]))); return NJS_OK; } @@ -144,19 +176,32 @@ static njs_int_t njs_object_math_atan2(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num, y, x; + double y, x; + njs_int_t ret; - if (nargs > 2) { - y = njs_number(&args[1]); - x = njs_number(&args[2]); + if (njs_slow_path(nargs < 3)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - num = atan2(y, x); + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + y = njs_number(&args[1]); + x = njs_number(&args[2]); + + njs_set_number(&vm->retval, atan2(y, x)); return NJS_OK; } @@ -166,16 +211,21 @@ static njs_int_t njs_object_math_atanh(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = atanh(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, atanh(njs_number(&args[1]))); return NJS_OK; } @@ -185,16 +235,21 @@ static njs_int_t njs_object_math_cbrt(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = cbrt(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, cbrt(njs_number(&args[1]))); return NJS_OK; } @@ -204,16 +259,21 @@ static njs_int_t njs_object_math_ceil(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = ceil(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, ceil(njs_number(&args[1]))); return NJS_OK; } @@ -223,18 +283,25 @@ static njs_int_t njs_object_math_clz32(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; - uint32_t ui32; + uint32_t ui32; + njs_int_t ret; - if (nargs > 1) { - ui32 = njs_number_to_uint32(njs_number(&args[1])); - num = njs_leading_zeros(ui32); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, 32); + return NJS_OK; + } + + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_uint32(vm, &args[1], &ui32); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } else { - num = 32; + ui32 = njs_number_to_uint32(njs_number(&args[1])); } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, njs_leading_zeros(ui32)); return NJS_OK; } @@ -244,16 +311,21 @@ static njs_int_t njs_object_math_cos(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = cos(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, cos(njs_number(&args[1]))); return NJS_OK; } @@ -263,16 +335,21 @@ static njs_int_t njs_object_math_cosh(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = cosh(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, cosh(njs_number(&args[1]))); return NJS_OK; } @@ -282,16 +359,21 @@ static njs_int_t njs_object_math_exp(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = exp(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, exp(njs_number(&args[1]))); return NJS_OK; } @@ -301,16 +383,21 @@ static njs_int_t njs_object_math_expm1(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = expm1(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, expm1(njs_number(&args[1]))); return NJS_OK; } @@ -320,16 +407,21 @@ static njs_int_t njs_object_math_floor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = floor(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, floor(njs_number(&args[1]))); return NJS_OK; } @@ -339,16 +431,21 @@ static njs_int_t njs_object_math_fround(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = (float) njs_number(&args[1]); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, (float) njs_number(&args[1])); return NJS_OK; } @@ -391,20 +488,35 @@ static njs_int_t njs_object_math_imul(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; - uint32_t a, b; + uint32_t a, b; + njs_int_t ret; + + if (njs_slow_path(nargs < 3)) { + njs_set_number(&vm->retval, 0); + return NJS_OK; + } - if (nargs > 2) { + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_uint32(vm, &args[1], &a); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { a = njs_number_to_uint32(njs_number(&args[1])); - b = njs_number_to_uint32(njs_number(&args[2])); + } - num = (int32_t) (a * b); + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_uint32(vm, &args[2], &b); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } else { - num = 0; + b = njs_number_to_uint32(njs_number(&args[2])); } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, (int32_t) (a * b)); return NJS_OK; } @@ -414,16 +526,21 @@ static njs_int_t njs_object_math_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = log(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, log(njs_number(&args[1]))); return NJS_OK; } @@ -433,16 +550,21 @@ static njs_int_t njs_object_math_log10(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = log10(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, log10(njs_number(&args[1]))); return NJS_OK; } @@ -452,16 +574,21 @@ static njs_int_t njs_object_math_log1p(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = log1p(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, log1p(njs_number(&args[1]))); return NJS_OK; } @@ -471,25 +598,31 @@ static njs_int_t njs_object_math_log2(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + double num; + njs_int_t ret; - if (nargs > 1) { - num = njs_number(&args[1]); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } -#if (NJS_SOLARIS) - /* On Solaris 10 log(-1) returns -Infinity. */ - if (num < 0) { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } -#endif + } - num = log2(num); + num = njs_number(&args[1]); - } else { +#if (NJS_SOLARIS) + /* On Solaris 10 log(-1) returns -Infinity. */ + if (num < 0) { num = NAN; } +#endif - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, log2(num)); return NJS_OK; } @@ -573,24 +706,39 @@ static njs_int_t njs_object_math_pow(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num, base, exponent; + double num, base, exponent; + njs_int_t ret; - if (nargs > 2) { - base = njs_number(&args[1]); - exponent = njs_number(&args[2]); - - /* - * According to ECMA-262: - * 1. If exponent is NaN, the result should be NaN; - * 2. The result of Math.pow(+/-1, +/-Infinity) should be NaN. - */ + if (njs_slow_path(nargs < 3)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - if (fabs(base) != 1 || (!isnan(exponent) && !isinf(exponent))) { - num = pow(base, exponent); + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[2]))) { + ret = njs_value_to_numeric(vm, &args[2], &args[2]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } + } + + base = njs_number(&args[1]); + exponent = njs_number(&args[2]); + + /* + * According to ECMA-262: + * 1. If exponent is NaN, the result should be NaN; + * 2. The result of Math.pow(+/-1, +/-Infinity) should be NaN. + */ + + if (fabs(base) != 1 || (!isnan(exponent) && !isinf(exponent))) { + num = pow(base, exponent); } else { num = NAN; @@ -620,16 +768,21 @@ static njs_int_t njs_object_math_round(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = round(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, round(njs_number(&args[1]))); return NJS_OK; } @@ -639,17 +792,25 @@ static njs_int_t njs_object_math_sign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + double num; + njs_int_t ret; - if (nargs > 1) { - num = njs_number(&args[1]); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - if (!isnan(num) && num != 0) { - num = signbit(num) ? -1 : 1; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } + } - } else { - num = NAN; + num = njs_number(&args[1]); + + if (!isnan(num) && num != 0) { + num = signbit(num) ? -1 : 1; } njs_set_number(&vm->retval, num); @@ -662,16 +823,21 @@ static njs_int_t njs_object_math_sin(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = sin(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, sin(njs_number(&args[1]))); return NJS_OK; } @@ -681,16 +847,21 @@ static njs_int_t njs_object_math_sinh(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = sinh(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, sinh(njs_number(&args[1]))); return NJS_OK; } @@ -700,16 +871,21 @@ static njs_int_t njs_object_math_sqrt(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = sqrt(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, sqrt(njs_number(&args[1]))); return NJS_OK; } @@ -719,16 +895,21 @@ static njs_int_t njs_object_math_tan(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = tan(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, tan(njs_number(&args[1]))); return NJS_OK; } @@ -738,16 +919,21 @@ static njs_int_t njs_object_math_tanh(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = tanh(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, tanh(njs_number(&args[1]))); return NJS_OK; } @@ -757,16 +943,21 @@ static njs_int_t njs_object_math_trunc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + njs_int_t ret; - if (nargs > 1) { - num = trunc(njs_number(&args[1])); + if (njs_slow_path(nargs < 2)) { + njs_set_number(&vm->retval, NAN); + return NJS_OK; + } - } else { - num = NAN; + if (njs_slow_path(!njs_is_number(&args[1]))) { + ret = njs_value_to_numeric(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, trunc(njs_number(&args[1]))); return NJS_OK; } @@ -833,8 +1024,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("abs"), - .value = njs_native_function(njs_object_math_abs, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_abs, 1), .writable = 1, .configurable = 1, }, @@ -842,8 +1032,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("acos"), - .value = njs_native_function(njs_object_math_acos, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_acos, 1), .writable = 1, .configurable = 1, }, @@ -852,8 +1041,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("acosh"), - .value = njs_native_function(njs_object_math_acosh, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_acosh, 1), .writable = 1, .configurable = 1, }, @@ -861,8 +1049,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("asin"), - .value = njs_native_function(njs_object_math_asin, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_asin, 1), .writable = 1, .configurable = 1, }, @@ -871,8 +1058,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("asinh"), - .value = njs_native_function(njs_object_math_asinh, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_asinh, 1), .writable = 1, .configurable = 1, }, @@ -880,8 +1066,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("atan"), - .value = njs_native_function(njs_object_math_atan, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_atan, 1), .writable = 1, .configurable = 1, }, @@ -889,8 +1074,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("atan2"), - .value = njs_native_function(njs_object_math_atan2, 2, - NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_atan2, 2), .writable = 1, .configurable = 1, }, @@ -899,8 +1083,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("atanh"), - .value = njs_native_function(njs_object_math_atanh, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_atanh, 1), .writable = 1, .configurable = 1, }, @@ -909,8 +1092,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("cbrt"), - .value = njs_native_function(njs_object_math_cbrt, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_cbrt, 1), .writable = 1, .configurable = 1, }, @@ -918,8 +1100,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("ceil"), - .value = njs_native_function(njs_object_math_ceil, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_ceil, 1), .writable = 1, .configurable = 1, }, @@ -928,8 +1109,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("clz32"), - .value = njs_native_function(njs_object_math_clz32, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_clz32, 1), .writable = 1, .configurable = 1, }, @@ -937,8 +1117,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("cos"), - .value = njs_native_function(njs_object_math_cos, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_cos, 1), .writable = 1, .configurable = 1, }, @@ -947,8 +1126,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("cosh"), - .value = njs_native_function(njs_object_math_cosh, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_cosh, 1), .writable = 1, .configurable = 1, }, @@ -956,8 +1134,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("exp"), - .value = njs_native_function(njs_object_math_exp, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_exp, 1), .writable = 1, .configurable = 1, }, @@ -966,8 +1143,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("expm1"), - .value = njs_native_function(njs_object_math_expm1, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_expm1, 1), .writable = 1, .configurable = 1, }, @@ -975,8 +1151,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("floor"), - .value = njs_native_function(njs_object_math_floor, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_floor, 1), .writable = 1, .configurable = 1, }, @@ -985,8 +1160,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("fround"), - .value = njs_native_function(njs_object_math_fround, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_fround, 1), .writable = 1, .configurable = 1, }, @@ -995,7 +1169,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("hypot"), - .value = njs_native_function(njs_object_math_hypot, 2, 0), + .value = njs_native_function(njs_object_math_hypot, 2), .writable = 1, .configurable = 1, }, @@ -1004,8 +1178,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("imul"), - .value = njs_native_function(njs_object_math_imul, 2, - NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_imul, 2), .writable = 1, .configurable = 1, }, @@ -1013,8 +1186,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("log"), - .value = njs_native_function(njs_object_math_log, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_log, 1), .writable = 1, .configurable = 1, }, @@ -1023,8 +1195,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("log10"), - .value = njs_native_function(njs_object_math_log10, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_log10, 1), .writable = 1, .configurable = 1, }, @@ -1033,8 +1204,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("log1p"), - .value = njs_native_function(njs_object_math_log1p, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_log1p, 1), .writable = 1, .configurable = 1, }, @@ -1043,8 +1213,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("log2"), - .value = njs_native_function(njs_object_math_log2, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_log2, 1), .writable = 1, .configurable = 1, }, @@ -1052,7 +1221,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("max"), - .value = njs_native_function(njs_object_math_max, 2, 0), + .value = njs_native_function(njs_object_math_max, 2), .writable = 1, .configurable = 1, }, @@ -1060,7 +1229,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("min"), - .value = njs_native_function(njs_object_math_min, 2, 0), + .value = njs_native_function(njs_object_math_min, 2), .writable = 1, .configurable = 1, }, @@ -1068,8 +1237,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("pow"), - .value = njs_native_function(njs_object_math_pow, 2, - NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_pow, 2), .writable = 1, .configurable = 1, }, @@ -1077,7 +1245,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("random"), - .value = njs_native_function(njs_object_math_random, 0, 0), + .value = njs_native_function(njs_object_math_random, 0), .writable = 1, .configurable = 1, }, @@ -1085,8 +1253,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("round"), - .value = njs_native_function(njs_object_math_round, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_round, 1), .writable = 1, .configurable = 1, }, @@ -1095,8 +1262,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("sign"), - .value = njs_native_function(njs_object_math_sign, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_sign, 1), .writable = 1, .configurable = 1, }, @@ -1104,8 +1270,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("sin"), - .value = njs_native_function(njs_object_math_sin, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_sin, 1), .writable = 1, .configurable = 1, }, @@ -1114,8 +1279,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("sinh"), - .value = njs_native_function(njs_object_math_sinh, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_sinh, 1), .writable = 1, .configurable = 1, }, @@ -1123,8 +1287,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("sqrt"), - .value = njs_native_function(njs_object_math_sqrt, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_sqrt, 1), .writable = 1, .configurable = 1, }, @@ -1132,8 +1295,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("tan"), - .value = njs_native_function(njs_object_math_tan, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_tan, 1), .writable = 1, .configurable = 1, }, @@ -1142,8 +1304,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("tanh"), - .value = njs_native_function(njs_object_math_tanh, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_tanh, 1), .writable = 1, .configurable = 1, }, @@ -1152,8 +1313,7 @@ static const njs_object_prop_t njs_math_object_properties[] = { .type = NJS_PROPERTY, .name = njs_string("trunc"), - .value = njs_native_function(njs_object_math_trunc, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_object_math_trunc, 1), .writable = 1, .configurable = 1, }, diff --git a/src/njs_module.c b/src/njs_module.c index 68eef62e..1f3d508c 100644 --- a/src/njs_module.c +++ b/src/njs_module.c @@ -506,6 +506,7 @@ njs_int_t njs_module_require(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_int_t ret; njs_object_t *object; njs_module_t *module; njs_lvlhsh_query_t lhq; @@ -515,6 +516,13 @@ njs_module_require(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } + if (njs_slow_path(!njs_is_string(&args[1]))) { + ret = njs_value_to_string(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + njs_string_get(&args[1], &lhq.key); lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); lhq.proto = &njs_modules_hash_proto; diff --git a/src/njs_number.c b/src/njs_number.c index c74d2a72..b1f8fc11 100644 --- a/src/njs_number.c +++ b/src/njs_number.c @@ -241,14 +241,22 @@ njs_int_t njs_number_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_object_t *object; - const njs_value_t *value; + njs_int_t ret; + njs_value_t *value; + njs_object_t *object; if (nargs == 1) { - value = &njs_value_zero; + value = njs_value_arg(&njs_value_zero); } else { value = &args[1]; + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_numeric(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + } } if (vm->top_frame->ctor) { @@ -335,6 +343,29 @@ njs_number_is_nan(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } +static njs_int_t +njs_number_is_finite(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + double num; + const njs_value_t *value; + + value = &njs_value_false; + + if (nargs > 1 && njs_is_number(&args[1])) { + num = njs_number(&args[1]); + + if (!isnan(num) && !isinf(num)) { + value = &njs_value_true; + } + } + + vm->retval = *value; + + return NJS_OK; +} + + static const njs_object_prop_t njs_number_constructor_properties[] = { /* Number.name == "Number". */ @@ -415,7 +446,7 @@ static const njs_object_prop_t njs_number_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isFinite"), - .value = njs_native_function(njs_number_is_finite, 1, 0), + .value = njs_native_function(njs_number_is_finite, 1), .writable = 1, .configurable = 1, }, @@ -424,7 +455,7 @@ static const njs_object_prop_t njs_number_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isInteger"), - .value = njs_native_function(njs_number_is_integer, 1, 0), + .value = njs_native_function(njs_number_is_integer, 1), .writable = 1, .configurable = 1, }, @@ -433,7 +464,7 @@ static const njs_object_prop_t njs_number_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isSafeInteger"), - .value = njs_native_function(njs_number_is_safe_integer, 1, 0), + .value = njs_native_function(njs_number_is_safe_integer, 1), .writable = 1, .configurable = 1, }, @@ -442,7 +473,7 @@ static const njs_object_prop_t njs_number_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isNaN"), - .value = njs_native_function(njs_number_is_nan, 1, 0), + .value = njs_native_function(njs_number_is_nan, 1), .writable = 1, .configurable = 1, }, @@ -451,8 +482,7 @@ static const njs_object_prop_t njs_number_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("parseFloat"), - .value = njs_native_function(njs_number_parse_float, 1, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_number_parse_float, 1), .writable = 1, .configurable = 1, }, @@ -461,8 +491,7 @@ static const njs_object_prop_t njs_number_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("parseInt"), - .value = njs_native_function(njs_number_parse_int, 2, - NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_number_parse_int, 2), .writable = 1, .configurable = 1, }, @@ -506,7 +535,9 @@ static njs_int_t njs_number_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double number, radix; + double number; + int32_t radix; + njs_int_t ret; njs_value_t *value; value = &args[0]; @@ -524,7 +555,10 @@ njs_number_prototype_to_string(njs_vm_t *vm, njs_value_t *args, } if (nargs > 1) { - radix = njs_number(&args[1]); + ret = njs_value_to_int32(vm, &args[1], &radix); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } if (radix < 2 || radix > 36 || radix != (int) radix) { njs_range_error(vm, NULL); @@ -671,17 +705,17 @@ njs_number_prototype_to_precision(njs_vm_t *vm, njs_value_t *args, return njs_number_to_string(vm, &vm->retval, value); } + ret = njs_value_to_integer(vm, njs_argument(args, 1), &precision); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + number = njs_number(value); if (njs_slow_path(isnan(number) || isinf(number))) { return njs_number_to_string(vm, &vm->retval, value); } - ret = njs_value_to_integer(vm, njs_argument(args, 1), &precision); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - if (njs_slow_path(precision < 1 || precision > 100)) { njs_range_error(vm, "precision argument must be between 1 and 100"); return NJS_ERROR; @@ -701,7 +735,7 @@ njs_number_prototype_to_exponential(njs_vm_t *vm, njs_value_t *args, size_t size; int64_t frac; njs_int_t ret; - njs_value_t *value; + njs_value_t *value, *value_frac; u_char buf[128]; value = &args[0]; @@ -717,18 +751,20 @@ njs_number_prototype_to_exponential(njs_vm_t *vm, njs_value_t *args, } } + value_frac = njs_arg(args, nargs, 1); + + ret = njs_value_to_integer(vm, value_frac, &frac); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + number = njs_number(value); if (njs_slow_path(isnan(number) || isinf(number))) { return njs_number_to_string(vm, &vm->retval, value); } - if (njs_is_defined(njs_arg(args, nargs, 1))) { - ret = njs_value_to_integer(vm, njs_argument(args, 1), &frac); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - + if (njs_is_defined(value_frac)) { if (njs_slow_path(frac < 0 || frac > 100)) { njs_range_error(vm, "digits argument must be between 0 and 100"); return NJS_ERROR; @@ -887,7 +923,7 @@ static const njs_object_prop_t njs_number_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("valueOf"), - .value = njs_native_function(njs_number_prototype_value_of, 0, 0), + .value = njs_native_function(njs_number_prototype_value_of, 0), .writable = 1, .configurable = 1, }, @@ -895,8 +931,7 @@ static const njs_object_prop_t njs_number_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_number_prototype_to_string, 1, - NJS_SKIP_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_number_prototype_to_string, 1), .writable = 1, .configurable = 1, }, @@ -904,8 +939,7 @@ static const njs_object_prop_t njs_number_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toFixed"), - .value = njs_native_function(njs_number_prototype_to_fixed, 1, - NJS_SKIP_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_number_prototype_to_fixed, 1), .writable = 1, .configurable = 1, }, @@ -913,8 +947,7 @@ static const njs_object_prop_t njs_number_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toPrecision"), - .value = njs_native_function(njs_number_prototype_to_precision, 1, - NJS_SKIP_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_number_prototype_to_precision, 1), .writable = 1, .configurable = 1, }, @@ -922,8 +955,7 @@ static const njs_object_prop_t njs_number_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toExponential"), - .value = njs_native_function(njs_number_prototype_to_exponential, 1, - NJS_SKIP_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_number_prototype_to_exponential, 1), .writable = 1, .configurable = 1, }, @@ -941,38 +973,33 @@ njs_int_t njs_number_global_is_nan(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - const njs_value_t *value; + double num; + njs_int_t ret; - value = &njs_value_true; - - if (nargs > 1 && !isnan(njs_number(&args[1]))) { - value = &njs_value_false; + ret = njs_value_to_number(vm, njs_arg(args, nargs, 1), &num); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - vm->retval = *value; + njs_set_boolean(&vm->retval, isnan(num)); return NJS_OK; } njs_int_t -njs_number_is_finite(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, +njs_number_global_is_finite(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; - const njs_value_t *value; + double num; + njs_int_t ret; - value = &njs_value_false; - - if (nargs > 1 && njs_is_number(&args[1])) { - num = njs_number(&args[1]); - - if (!isnan(num) && !isinf(num)) { - value = &njs_value_true; - } + ret = njs_value_to_number(vm, njs_arg(args, nargs, 1), &num); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - vm->retval = *value; + njs_set_boolean(&vm->retval, !(isnan(num) || isinf(num))); return NJS_OK; } @@ -982,72 +1009,88 @@ njs_int_t njs_number_parse_int(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; - int64_t n; - uint8_t radix; - njs_str_t string; - njs_bool_t minus, test_prefix; - const u_char *p, *end; + double num; + int64_t n; + int32_t radix; + njs_int_t ret; + njs_str_t string; + njs_bool_t minus, test_prefix; + njs_value_t *value; + const u_char *p, *end; num = NAN; - if (nargs > 1) { - njs_string_get(&args[1], &string); + if (nargs < 2) { + goto done; + } - end = string.start + string.length; + value = njs_argument(args, 1); - for (p = string.start; p < end; p++) { - if (*p != ' ') { - goto found; - } + if (!njs_is_string(value)) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } + } - goto done; + njs_string_get(value, &string); - found: + end = string.start + string.length; - minus = 0; + for (p = string.start; p < end; p++) { + if (*p != ' ') { + goto found; + } + } - if (p[0] == '-') { - p++; - minus = 1; + goto done; - } else if (p[0] == '+') { - p++; - } +found: - test_prefix = (end - p > 1); - radix = 0; + minus = 0; - if (nargs > 2) { - radix = njs_number(&args[2]); + if (p[0] == '-') { + p++; + minus = 1; - if (radix != 0) { - if (radix < 2 || radix > 36) { - goto done; - } + } else if (p[0] == '+') { + p++; + } - if (radix != 16) { - test_prefix = 0; - } - } - } + test_prefix = (end - p > 1); + radix = 0; - if (radix == 0) { - radix = 10; + if (nargs > 2) { + ret = njs_value_to_int32(vm, njs_argument(args, 2), &radix); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - if (test_prefix && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { - p += 2; - radix = 16; + if (radix != 0) { + if (radix < 2 || radix > 36) { + goto done; + } + + if (radix != 16) { + test_prefix = 0; + } } + } - n = njs_number_radix_parse(&p, end, radix); + if (radix == 0) { + radix = 10; + } - if (n >= 0) { - num = n; - num = minus ? -num : num; - } + if (test_prefix && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + p += 2; + radix = 16; + } + + n = njs_number_radix_parse(&p, end, radix); + + if (n >= 0) { + num = n; + num = minus ? -num : num; } done: @@ -1062,11 +1105,17 @@ njs_int_t njs_number_parse_float(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; + double num; + njs_int_t ret; num = NAN; if (nargs > 1) { + ret = njs_value_to_string(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + num = njs_string_to_number(&args[1], 1); } diff --git a/src/njs_number.h b/src/njs_number.h index 5924e6da..3fcc5c0b 100644 --- a/src/njs_number.h +++ b/src/njs_number.h @@ -21,7 +21,7 @@ njs_int_t njs_number_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); njs_int_t njs_number_global_is_nan(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); -njs_int_t njs_number_is_finite(njs_vm_t *vm, njs_value_t *args, +njs_int_t njs_number_global_is_finite(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); njs_int_t njs_number_parse_int(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); diff --git a/src/njs_object.c b/src/njs_object.c index d29ce635..cb17691e 100644 --- a/src/njs_object.c +++ b/src/njs_object.c @@ -1112,6 +1112,18 @@ njs_object_define_property(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, name = njs_arg(args, nargs, 2); + if (njs_slow_path(!njs_is_string(name))) { + if (njs_is_undefined(name)) { + name = njs_value_arg(&njs_string_undefined); + + } else { + ret = njs_value_to_string(vm, name, name); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + } + ret = njs_object_prop_define(vm, value, name, desc, NJS_OBJECT_PROP_DESCRIPTOR); if (njs_slow_path(ret != NJS_OK)) { @@ -1679,7 +1691,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("create"), - .value = njs_native_function(njs_object_create, 2, 0), + .value = njs_native_function(njs_object_create, 2), .writable = 1, .configurable = 1, }, @@ -1688,8 +1700,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("keys"), - .value = njs_native_function(njs_object_keys, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_keys, 1), .writable = 1, .configurable = 1, }, @@ -1698,8 +1709,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("values"), - .value = njs_native_function(njs_object_values, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_values, 1), .writable = 1, .configurable = 1, }, @@ -1708,8 +1718,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("entries"), - .value = njs_native_function(njs_object_entries, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_entries, 1), .writable = 1, .configurable = 1, }, @@ -1718,9 +1727,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("defineProperty"), - .value = njs_native_function(njs_object_define_property, 3, - NJS_SKIP_ARG, NJS_OBJECT_ARG, - NJS_STRING_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_define_property, 3), .writable = 1, .configurable = 1, }, @@ -1729,9 +1736,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("defineProperties"), - .value = njs_native_function(njs_object_define_properties, 2, - NJS_SKIP_ARG, NJS_OBJECT_ARG, - NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_define_properties, 2), .writable = 1, .configurable = 1, }, @@ -1740,9 +1745,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("getOwnPropertyDescriptor"), - .value = njs_native_function(njs_object_get_own_property_descriptor, 2, - NJS_SKIP_ARG, NJS_SKIP_ARG, - NJS_STRING_ARG), + .value = njs_native_function(njs_object_get_own_property_descriptor, 2), .writable = 1, .configurable = 1, }, @@ -1751,8 +1754,8 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("getOwnPropertyDescriptors"), - .value = njs_native_function(njs_object_get_own_property_descriptors, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_get_own_property_descriptors, + 1), .writable = 1, .configurable = 1, }, @@ -1761,8 +1764,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("getOwnPropertyNames"), - .value = njs_native_function(njs_object_get_own_property_names, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_get_own_property_names, 1), .writable = 1, .configurable = 1, }, @@ -1771,8 +1773,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("getPrototypeOf"), - .value = njs_native_function(njs_object_get_prototype_of, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_get_prototype_of, 1), .writable = 1, .configurable = 1, }, @@ -1781,8 +1782,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("freeze"), - .value = njs_native_function(njs_object_freeze, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_freeze, 1), .writable = 1, .configurable = 1, }, @@ -1791,8 +1791,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isFrozen"), - .value = njs_native_function(njs_object_is_frozen, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_is_frozen, 1), .writable = 1, .configurable = 1, }, @@ -1801,8 +1800,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("seal"), - .value = njs_native_function(njs_object_seal, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_seal, 1), .writable = 1, .configurable = 1, }, @@ -1811,8 +1809,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isSealed"), - .value = njs_native_function(njs_object_is_sealed, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_is_sealed, 1), .writable = 1, .configurable = 1, }, @@ -1821,8 +1818,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("preventExtensions"), - .value = njs_native_function(njs_object_prevent_extensions, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_prevent_extensions, 1), .writable = 1, .configurable = 1, }, @@ -1831,8 +1827,7 @@ static const njs_object_prop_t njs_object_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isExtensible"), - .value = njs_native_function(njs_object_is_extensible, 1, - NJS_SKIP_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_is_extensible, 1), .writable = 1, .configurable = 1, }, @@ -2207,6 +2202,11 @@ njs_object_prototype_is_prototype_of(njs_vm_t *vm, njs_value_t *args, njs_object_t *object, *proto; const njs_value_t *retval; + 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; + } + retval = &njs_value_false; prototype = &args[0]; value = njs_arg(args, nargs, 1); @@ -2253,7 +2253,7 @@ static const njs_object_prop_t njs_object_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("valueOf"), - .value = njs_native_function(njs_object_prototype_value_of, 0, 0), + .value = njs_native_function(njs_object_prototype_value_of, 0), .writable = 1, .configurable = 1, }, @@ -2261,7 +2261,7 @@ static const njs_object_prop_t njs_object_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_object_prototype_to_string, 0, 0), + .value = njs_native_function(njs_object_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -2269,8 +2269,7 @@ static const njs_object_prop_t njs_object_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("hasOwnProperty"), - .value = njs_native_function(njs_object_prototype_has_own_property, 1, - NJS_OBJECT_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_object_prototype_has_own_property, 1), .writable = 1, .configurable = 1, }, @@ -2278,8 +2277,8 @@ static const njs_object_prop_t njs_object_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("propertyIsEnumerable"), - .value = njs_native_function(njs_object_prototype_prop_is_enumerable, 1, - NJS_OBJECT_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_object_prototype_prop_is_enumerable, + 1), .writable = 1, .configurable = 1, }, @@ -2287,8 +2286,7 @@ static const njs_object_prop_t njs_object_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("isPrototypeOf"), - .value = njs_native_function(njs_object_prototype_is_prototype_of, 1, - NJS_OBJECT_ARG, NJS_OBJECT_ARG), + .value = njs_native_function(njs_object_prototype_is_prototype_of, 1), .writable = 1, .configurable = 1, }, diff --git a/src/njs_regexp.c b/src/njs_regexp.c index 3a453263..6f7ce2a2 100644 --- a/src/njs_regexp.c +++ b/src/njs_regexp.c @@ -845,7 +845,8 @@ njs_regexp_prototype_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_int_t ret; njs_uint_t n; njs_regex_t *regex; - const njs_value_t *value, *retval; + njs_value_t *value; + const njs_value_t *retval; njs_string_prop_t string; njs_regexp_pattern_t *pattern; njs_regex_match_data_t *match_data; @@ -858,8 +859,17 @@ njs_regexp_prototype_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, retval = &njs_value_false; value = njs_arg(args, nargs, 1); - if (njs_is_undefined(value)) { - value = &njs_string_undefined; + + if (!njs_is_string(value)) { + if (njs_is_undefined(value)) { + value = njs_value_arg(&njs_string_undefined); + + } else { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } } (void) njs_string_prop(&string, value); @@ -911,10 +921,10 @@ njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, { njs_int_t ret; njs_utf8_t utf8; + njs_value_t *value; njs_regexp_t *regexp; njs_string_prop_t string; njs_regexp_utf8_t type; - const njs_value_t *value; njs_regexp_pattern_t *pattern; njs_regex_match_data_t *match_data; @@ -924,8 +934,17 @@ njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } value = njs_arg(args, nargs, 1); - if (njs_is_undefined(value)) { - value = &njs_string_undefined; + + if (!njs_is_string(value)) { + if (njs_is_undefined(value)) { + value = njs_value_arg(&njs_string_undefined); + + } else { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } } regexp = njs_regexp(&args[0]); @@ -1232,7 +1251,7 @@ static const njs_object_prop_t njs_regexp_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_regexp_prototype_to_string, 0, 0), + .value = njs_native_function(njs_regexp_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -1240,8 +1259,7 @@ static const njs_object_prop_t njs_regexp_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("test"), - .value = njs_native_function(njs_regexp_prototype_test, 1, - NJS_OBJECT_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_regexp_prototype_test, 1), .writable = 1, .configurable = 1, }, @@ -1249,8 +1267,7 @@ static const njs_object_prop_t njs_regexp_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("exec"), - .value = njs_native_function(njs_regexp_prototype_exec, 1, - NJS_OBJECT_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_regexp_prototype_exec, 1), .writable = 1, .configurable = 1, }, diff --git a/src/njs_string.c b/src/njs_string.c index b9abfac4..1144cd27 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -54,10 +54,10 @@ static void njs_encode_base64_core(njs_str_t *dst, const njs_str_t *src, const u_char *basis, njs_uint_t padding); static njs_int_t njs_decode_base64_core(njs_vm_t *vm, njs_value_t *value, const njs_str_t *src, const u_char *basis); -static void njs_string_slice_prop(njs_string_prop_t *string, +static njs_int_t njs_string_slice_prop(njs_vm_t *vm, njs_string_prop_t *string, njs_slice_prop_t *slice, njs_value_t *args, njs_uint_t nargs); -static void njs_string_slice_args(njs_slice_prop_t *slice, njs_value_t *args, - njs_uint_t nargs); +static njs_int_t njs_string_slice_args(njs_vm_t *vm, njs_slice_prop_t *slice, + njs_value_t *args, njs_uint_t nargs); static njs_int_t njs_string_from_char_code(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); static njs_int_t njs_string_from_code_point(njs_vm_t *vm, njs_value_t *args, @@ -541,14 +541,22 @@ njs_int_t njs_string_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_object_t *object; - const njs_value_t *value; + njs_int_t ret; + njs_value_t *value; + njs_object_t *object; if (nargs == 1) { - value = &njs_string_empty; + value = njs_value_arg(&njs_string_empty); } else { value = &args[1]; + + if (njs_slow_path(!njs_is_string(value))) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } } if (vm->top_frame->ctor) { @@ -596,8 +604,7 @@ static const njs_object_prop_t njs_string_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("bytesFrom"), - .value = njs_native_function(njs_string_bytes_from, 0, NJS_SKIP_ARG, - NJS_SKIP_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_string_bytes_from, 0), .writable = 1, .configurable = 1, }, @@ -606,7 +613,7 @@ static const njs_object_prop_t njs_string_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("fromCharCode"), - .value = njs_native_function(njs_string_from_char_code, 1, 0), + .value = njs_native_function(njs_string_from_char_code, 1), .writable = 1, .configurable = 1, }, @@ -615,7 +622,7 @@ static const njs_object_prop_t njs_string_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("fromCodePoint"), - .value = njs_native_function(njs_string_from_code_point, 1, 0), + .value = njs_native_function(njs_string_from_code_point, 1), .writable = 1, .configurable = 1, }, @@ -928,6 +935,27 @@ njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } +njs_inline njs_int_t +njs_string_object_validate(njs_vm_t *vm, njs_value_t *object) +{ + njs_int_t ret; + + if (njs_slow_path(njs_is_null_or_undefined(object))) { + njs_type_error(vm, "cannot convert undefined to object"); + return NJS_ERROR; + } + + if (njs_slow_path(!njs_is_string(object))) { + ret = njs_value_to_string(vm, object, object); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + return NJS_OK; +} + + /* * String.fromUTF8(start[, end]). * The method converts an UTF-8 encoded byte string to an Unicode string. @@ -938,10 +966,19 @@ njs_string_prototype_from_utf8(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { ssize_t length; + njs_int_t ret; njs_slice_prop_t slice; njs_string_prop_t string; - njs_string_slice_prop(&string, &slice, args, nargs); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + ret = njs_string_slice_prop(vm, &string, &slice, args, nargs); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } if (string.length != 0) { /* ASCII or UTF8 string. */ @@ -972,15 +1009,24 @@ static njs_int_t njs_string_prototype_to_utf8(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_int_t ret; njs_slice_prop_t slice; njs_string_prop_t string; - (void) njs_string_prop(&string, &args[0]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + (void) njs_string_prop(&string, njs_argument(args, 0)); string.length = 0; slice.string_length = string.size; - njs_string_slice_args(&slice, args, nargs); + ret = njs_string_slice_args(vm, &slice, args, nargs); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } return njs_string_slice(vm, &vm->retval, &string, &slice); } @@ -997,10 +1043,19 @@ njs_string_prototype_from_bytes(njs_vm_t *vm, njs_value_t *args, { u_char *p, *s, *start, *end; size_t size; + njs_int_t ret; njs_slice_prop_t slice; njs_string_prop_t string; - njs_string_slice_prop(&string, &slice, args, nargs); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + ret = njs_string_slice_prop(vm, &string, &slice, args, nargs); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } if (string.length != 0) { /* ASCII or UTF8 string. */ @@ -1052,11 +1107,20 @@ njs_string_prototype_to_bytes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, u_char *p; size_t length; uint32_t byte; + njs_int_t ret; const u_char *s, *end; njs_slice_prop_t slice; njs_string_prop_t string; - njs_string_slice_prop(&string, &slice, args, nargs); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + ret = njs_string_slice_prop(vm, &string, &slice, args, nargs); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } if (string.length == 0) { /* Byte string. */ @@ -1110,10 +1174,19 @@ static njs_int_t njs_string_prototype_slice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_int_t ret; njs_slice_prop_t slice; njs_string_prop_t string; - njs_string_slice_prop(&string, &slice, args, nargs); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + ret = njs_string_slice_prop(vm, &string, &slice, args, nargs); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } return njs_string_slice(vm, &vm->retval, &string, &slice); } @@ -1128,17 +1201,34 @@ static njs_int_t njs_string_prototype_substring(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - ssize_t start, end, length; + int64_t start, end, length; + njs_int_t ret; + njs_value_t *value; njs_slice_prop_t slice; njs_string_prop_t string; - length = njs_string_prop(&string, &args[0]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + length = njs_string_prop(&string, njs_argument(args, 0)); slice.string_length = length; start = 0; if (nargs > 1) { - start = njs_number(&args[1]); + value = njs_argument(args, 1); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &start); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + start = njs_number_to_integer(njs_number(value)); + } if (start < 0) { start = 0; @@ -1150,7 +1240,17 @@ njs_string_prototype_substring(njs_vm_t *vm, njs_value_t *args, end = length; if (nargs > 2) { - end = njs_number(&args[2]); + value = njs_arg(args, nargs, 2); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &end); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + end = njs_number_to_integer(njs_number(value)); + } if (end < 0) { end = 0; @@ -1184,17 +1284,34 @@ static njs_int_t njs_string_prototype_substr(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - ssize_t start, length, n; + int64_t start, length, n; + njs_int_t ret; + njs_value_t *value; njs_slice_prop_t slice; njs_string_prop_t string; - length = njs_string_prop(&string, &args[0]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + length = njs_string_prop(&string, njs_argument(args, 0)); slice.string_length = length; start = 0; if (nargs > 1) { - start = njs_number(&args[1]); + value = njs_arg(args, nargs, 1); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &start); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + start = njs_number_to_integer(njs_number(value)); + } if (start < length) { if (start < 0) { @@ -1208,7 +1325,17 @@ njs_string_prototype_substr(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, length -= start; if (nargs > 2) { - n = njs_number(&args[2]); + value = njs_arg(args, nargs, 2); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + n = njs_number_to_integer(njs_number(value)); + } if (n < 0) { length = 0; @@ -1241,7 +1368,12 @@ njs_string_prototype_char_at(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_slice_prop_t slice; njs_string_prop_t string; - slice.string_length = njs_string_prop(&string, &args[0]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + slice.string_length = njs_string_prop(&string, njs_argument(args, 0)); ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &start); if (njs_slow_path(ret != NJS_OK)) { @@ -1262,27 +1394,37 @@ njs_string_prototype_char_at(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static void -njs_string_slice_prop(njs_string_prop_t *string, njs_slice_prop_t *slice, - njs_value_t *args, njs_uint_t nargs) +static njs_int_t +njs_string_slice_prop(njs_vm_t *vm, njs_string_prop_t *string, + njs_slice_prop_t *slice, njs_value_t *args, njs_uint_t nargs) { slice->string_length = njs_string_prop(string, &args[0]); - njs_string_slice_args(slice, args, nargs); + return njs_string_slice_args(vm, slice, args, nargs); } -static void -njs_string_slice_args(njs_slice_prop_t *slice, njs_value_t *args, +static njs_int_t +njs_string_slice_args(njs_vm_t *vm, njs_slice_prop_t *slice, njs_value_t *args, njs_uint_t nargs) { - ssize_t start, end, length; + int64_t start, end, length; + njs_int_t ret; njs_value_t *value; length = slice->string_length; value = njs_arg(args, nargs, 1); - start = njs_number(value); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &start); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + start = njs_number_to_integer(njs_number(value)); + } if (start < 0) { start += length; @@ -1297,12 +1439,21 @@ njs_string_slice_args(njs_slice_prop_t *slice, njs_value_t *args, length = 0; } else { - if (njs_is_defined(njs_arg(args, nargs, 2))) { - value = njs_argument(args, 2); - end = njs_number(value); + value = njs_arg(args, nargs, 2); + + if (njs_slow_path(!njs_is_number(value))) { + if (njs_is_defined(value)) { + ret = njs_value_to_integer(vm, value, &end); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + end = length; + } } else { - end = length; + end = njs_number_to_integer(njs_number(value)); } if (end < 0) { @@ -1324,6 +1475,8 @@ njs_string_slice_args(njs_slice_prop_t *slice, njs_value_t *args, slice->start = start; slice->length = length; + + return NJS_OK; } @@ -1408,7 +1561,12 @@ njs_string_prototype_char_code_at(njs_vm_t *vm, njs_value_t *args, const u_char *start, *end; njs_string_prop_t string; - length = njs_string_prop(&string, &args[0]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + length = njs_string_prop(&string, njs_argument(args, 0)); ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &index); if (njs_slow_path(ret != NJS_OK)) { @@ -1807,18 +1965,45 @@ static njs_int_t njs_string_prototype_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - ssize_t index, length, search_length; + int64_t index, length, search_length; + njs_int_t ret; + njs_value_t *value; const u_char *p, *end; njs_string_prop_t string, search; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + if (nargs > 1) { - length = njs_string_prop(&string, &args[0]); - search_length = njs_string_prop(&search, &args[1]); + length = njs_string_prop(&string, njs_argument(args, 0)); + + value = njs_argument(args, 1); + + if (njs_slow_path(!njs_is_string(value))) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + search_length = njs_string_prop(&search, value); index = 0; if (nargs > 2) { - index = njs_number(&args[2]); + value = njs_argument(args, 2); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &index); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + index = njs_number_to_integer(njs_number(value)); + } if (index < 0) { index = 0; @@ -1879,18 +2064,34 @@ njs_string_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args, { double pos; ssize_t index, start, length, search_length; + njs_int_t ret; + njs_value_t *value; const u_char *p, *end; const njs_value_t *search_string; njs_string_prop_t string, search; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + index = -1; - length = njs_string_prop(&string, njs_arg(args, nargs, 0)); + length = njs_string_prop(&string, njs_argument(args, 0)); search_string = njs_arg(args, nargs, 1); - if (njs_is_undefined(search_string)) { - search_string = &njs_string_undefined; + if (njs_slow_path(!njs_is_string(search_string))) { + if (njs_is_undefined(search_string)) { + search_string = &njs_string_undefined; + + } else { + ret = njs_value_to_string(vm, njs_value_arg(search_string), + njs_value_arg(search_string)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } } search_length = njs_string_prop(&search, search_string); @@ -1899,7 +2100,17 @@ njs_string_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args, goto done; } - pos = njs_number(njs_arg(args, nargs, 2)); + value = njs_arg(args, nargs, 2); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_number(vm, value, &pos); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + pos = njs_number(value); + } if (isnan(pos)) { index = NJS_STRING_MAX_LENGTH; @@ -1981,32 +2192,59 @@ static njs_int_t njs_string_prototype_includes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - ssize_t index, length, search_length; + int64_t index, length, search_length; + njs_int_t ret; + njs_value_t *value; const u_char *p, *end; const njs_value_t *retval; njs_string_prop_t string, search; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + retval = &njs_value_true; if (nargs > 1) { - search_length = njs_string_prop(&search, &args[1]); + value = njs_argument(args, 1); - if (search_length == 0) { - goto done; + if (njs_slow_path(!njs_is_string(value))) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } - length = njs_string_prop(&string, &args[0]); - - index = 0; + search_length = njs_string_prop(&search, value); if (nargs > 2) { - index = njs_number(&args[2]); + value = njs_argument(args, 2); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &index); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + index = njs_number_to_integer(njs_number(value)); + } if (index < 0) { index = 0; } + + } else { + index = 0; + } + + if (search_length == 0) { + goto done; } + length = njs_string_prop(&string, &args[0]); + if (length - index >= search_length) { end = string.start + string.size; @@ -2061,23 +2299,58 @@ static njs_int_t njs_string_starts_or_ends_with(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_bool_t starts) { - ssize_t index, length, search_length; + int64_t index, length, search_length; + njs_int_t ret; + njs_value_t *value; const u_char *p, *end; const njs_value_t *retval; njs_string_prop_t string, search; retval = &njs_value_true; - if (nargs > 1) { - search_length = njs_string_prop(&search, &args[1]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } - if (search_length == 0) { - goto done; + value = njs_arg(args, nargs, 1); + + if (njs_slow_path(!njs_is_string(value))) { + if (njs_is_undefined(value)) { + value = njs_value_arg(&njs_string_undefined); + + } else { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } + } - length = njs_string_prop(&string, &args[0]); + search_length = njs_string_prop(&search, value); + + value = njs_arg(args, nargs, 2); + + if (njs_slow_path(!njs_is_number(value))) { + index = -1; + + if (!njs_is_undefined(value)) { + ret = njs_value_to_integer(vm, value, &index); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + } else { + index = njs_number_to_integer(njs_number(value)); + } - index = (nargs > 2) ? njs_number(&args[2]) : -1; + if (search_length == 0) { + goto done; + } + + if (nargs > 1) { + length = njs_string_prop(&string, &args[0]); if (starts) { if (index < 0) { @@ -2247,10 +2520,16 @@ njs_string_prototype_to_lower_case(njs_vm_t *vm, njs_value_t *args, size_t size, length; u_char *p; uint32_t code; + njs_int_t ret; const u_char *s, *end; njs_string_prop_t string; - (void) njs_string_prop(&string, &args[0]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + (void) njs_string_prop(&string, njs_argument(args, 0)); if (string.length == 0 || string.length == string.size) { /* Byte or ASCII string. */ @@ -2314,10 +2593,16 @@ njs_string_prototype_to_upper_case(njs_vm_t *vm, njs_value_t *args, size_t size, length; u_char *p; uint32_t code; + njs_int_t ret; const u_char *s, *end; njs_string_prop_t string; - (void) njs_string_prop(&string, &args[0]); + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + (void) njs_string_prop(&string, njs_argument(args, 0)); if (string.length == 0 || string.length == string.size) { /* Byte or ASCII string. */ @@ -2372,7 +2657,15 @@ static njs_int_t njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_string_trim(vm, &args[0], NJS_TRIM_START|NJS_TRIM_END); + njs_int_t ret; + + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + return njs_string_trim(vm, njs_argument(args, 0), + NJS_TRIM_START|NJS_TRIM_END); } @@ -2380,7 +2673,14 @@ static njs_int_t njs_string_prototype_trim_start(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_string_trim(vm, &args[0], NJS_TRIM_START); + njs_int_t ret; + + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + return njs_string_trim(vm, njs_argument(args, 0), NJS_TRIM_START); } @@ -2388,7 +2688,14 @@ static njs_int_t njs_string_prototype_trim_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - return njs_string_trim(vm, &args[0], NJS_TRIM_END); + njs_int_t ret; + + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + return njs_string_trim(vm, njs_argument(args, 0), NJS_TRIM_END); } @@ -2517,12 +2824,17 @@ njs_string_prototype_repeat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_int_t ret; njs_string_prop_t string; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &n); if (njs_slow_path(ret != NJS_OK)) { return ret; } - (void) njs_string_prop(&string, &args[0]); + (void) njs_string_prop(&string, njs_argument(args, 0)); max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size : NJS_STRING_MAX_LENGTH; @@ -2579,16 +2891,37 @@ njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, { u_char *p, *start; size_t padding, trunc, new_size; - int32_t length, new_length; + int64_t length, new_length; uint32_t n, pad_length; + njs_int_t ret; + njs_value_t *value, *pad; const u_char *end; - const njs_value_t *pad; njs_string_prop_t string, pad_string; static const njs_value_t string_space = njs_string(" "); - length = njs_string_prop(&string, &args[0]); - new_length = nargs > 1 ? njs_number(&args[1]) : 0; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + length = njs_string_prop(&string, njs_argument(args, 0)); + + new_length = 0; + + if (nargs > 1) { + value = njs_argument(args, 1); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_integer(vm, value, &new_length); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + new_length = njs_number_to_integer(njs_number(value)); + } + } if (new_length <= length) { vm->retval = args[0]; @@ -2607,7 +2940,18 @@ njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, trunc = 0; pad = njs_arg(args, nargs, 2); - pad = njs_is_undefined(pad) ? &string_space : pad; + + if (njs_slow_path(!njs_is_string(pad))) { + if (njs_is_undefined(pad)) { + pad = njs_value_arg(&string_space); + + } else { + ret = njs_value_to_string(vm, pad, pad); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_OK; + } + } + } pad_length = njs_string_prop(&pad_string, pad); @@ -2673,24 +3017,41 @@ static njs_int_t njs_string_prototype_search(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int ret, *captures; - njs_int_t index; + int *captures; + njs_int_t ret, index; njs_uint_t n; + njs_value_t *value; njs_string_prop_t string; njs_regexp_pattern_t *pattern; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + index = 0; if (nargs > 1) { + value = njs_argument(args, 1); - switch (args[1].type) { + switch (value->type) { case NJS_REGEXP: - pattern = njs_regexp_pattern(&args[1]); + pattern = njs_regexp_pattern(value); break; - case NJS_STRING: - (void) njs_string_prop(&string, &args[1]); + case NJS_UNDEFINED: + goto done; + + default: + if (njs_slow_path(!njs_is_string(value))) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + (void) njs_string_prop(&string, value); if (string.size != 0) { pattern = njs_regexp_pattern_create(vm, string.start, @@ -2703,10 +3064,6 @@ njs_string_prototype_search(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } goto done; - - case NJS_UNDEFINED: - default: - goto done; } index = -1; @@ -2749,6 +3106,11 @@ njs_string_prototype_match(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_value_t arguments[2]; njs_regexp_pattern_t *pattern; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + arguments[1] = args[0]; string.start = NULL; @@ -2772,8 +3134,17 @@ njs_string_prototype_match(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto match; } - if (njs_is_string(&args[1])) { - /* string1.match(string2) is the same as /string2/.exec(string1). */ + if (!njs_is_string(&args[1])) { + if (!njs_is_undefined(&args[1])) { + ret = njs_value_to_string(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + njs_string_get(&args[1], &string); + } + + } else { njs_string_get(&args[1], &string); } @@ -2899,16 +3270,23 @@ static njs_int_t njs_string_prototype_split(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int ret, *captures; + int *captures; size_t size; uint32_t limit; + njs_int_t ret; njs_utf8_t utf8; + njs_value_t *value; njs_array_t *array; const u_char *p, *start, *next, *last, *end; njs_regexp_utf8_t type; njs_string_prop_t string, split; njs_regexp_pattern_t *pattern; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE); if (njs_slow_path(array == NULL)) { return NJS_ERROR; @@ -2917,7 +3295,17 @@ njs_string_prototype_split(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (nargs > 1) { if (nargs > 2) { - limit = njs_number(&args[2]); + value = njs_argument(args, 2); + + if (njs_slow_path(!njs_is_number(value))) { + ret = njs_value_to_uint32(vm, value, &limit); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + limit = njs_number_to_uint32(njs_number(value)); + } if (limit == 0) { goto done; @@ -2947,31 +3335,34 @@ njs_string_prototype_split(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, switch (args[1].type) { - case NJS_STRING: - (void) njs_string_prop(&split, &args[1]); + case NJS_REGEXP: + pattern = njs_regexp_pattern(&args[1]); - if (string.size < split.size) { + if (!njs_regex_is_valid(&pattern->regex[type])) { goto single; } start = string.start; end = string.start + string.size; - last = end - split.size; do { - for (p = start; p <= last; p++) { - if (memcmp(p, split.start, split.size) == 0) { - goto found; - } - } + ret = njs_regexp_match(vm, &pattern->regex[type], start, + end - start, vm->single_match_data); + if (ret >= 0) { + captures = njs_regex_captures(vm->single_match_data); - p = end; + p = start + captures[0]; + next = start + captures[1]; -found: + } else if (ret == NJS_REGEX_NOMATCH) { + p = (u_char *) end; + next = (u_char *) end + 1; - next = p + split.size; + } else { + return NJS_ERROR; + } - /* Empty split string. */ + /* Empty split regexp. */ if (p == next) { p = (utf8 != NJS_STRING_BYTE) ? njs_utf8_next(p, end) : p + 1; @@ -2992,34 +3383,41 @@ found: goto done; - case NJS_REGEXP: - pattern = njs_regexp_pattern(&args[1]); + case NJS_UNDEFINED: + break; - if (!njs_regex_is_valid(&pattern->regex[type])) { + default: + if (njs_slow_path(!njs_is_string(&args[1]))) { + ret = njs_value_to_string(vm, &args[1], &args[1]); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + (void) njs_string_prop(&split, &args[1]); + + if (string.size < split.size) { goto single; } start = string.start; end = string.start + string.size; + last = end - split.size; do { - ret = njs_regexp_match(vm, &pattern->regex[type], start, - end - start, vm->single_match_data); - if (ret >= 0) { - captures = njs_regex_captures(vm->single_match_data); + for (p = start; p <= last; p++) { + if (memcmp(p, split.start, split.size) == 0) { + goto found; + } + } - p = start + captures[0]; - next = start + captures[1]; + p = end; - } else if (ret == NJS_REGEX_NOMATCH) { - p = (u_char *) end; - next = (u_char *) end + 1; +found: - } else { - return NJS_ERROR; - } + next = p + split.size; - /* Empty split regexp. */ + /* Empty split string. */ if (p == next) { p = (utf8 != NJS_STRING_BYTE) ? njs_utf8_next(p, end) : p + 1; @@ -3039,10 +3437,6 @@ found: } while (limit != 0 && p < end); goto done; - - case NJS_UNDEFINED: - default: - break; } } @@ -3088,20 +3482,12 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_string_prop_t string; njs_string_replace_t *r, string_replace; - this = njs_arg(args, nargs, 0); - - if (njs_slow_path(njs_value_is_null_or_undefined(this))) { - njs_type_error(vm, "\"this\" argument cannot be " - "undefined or null value"); - return NJS_ERROR; + ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - if (!njs_is_string(this)) { - ret = njs_value_to_string(vm, this, this); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } + this = njs_argument(args, 0); if (nargs == 1) { goto original; @@ -3142,6 +3528,18 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } else { regex = NULL; ncaptures = 1; + + if (!njs_is_string(search)) { + if (njs_is_undefined(search)) { + search = njs_value_arg(&njs_string_undefined); + + } else { + ret = njs_value_to_string(vm, search, search); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + } } /* This cannot fail. */ @@ -3160,10 +3558,15 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, r->function = njs_function(replace); } else { - if (!njs_is_string(replace)) { - ret = njs_value_to_string(vm, replace, replace); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + if (njs_slow_path(!njs_is_string(replace))) { + if (njs_is_undefined(replace)) { + replace = njs_value_arg(&njs_string_undefined); + + } else { + ret = njs_value_to_string(vm, replace, replace); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } } } @@ -3206,13 +3609,6 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return njs_string_replace_regexp(vm, this, search, r); } - if (!njs_is_string(search)) { - ret = njs_value_to_string(vm, search, search); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - return njs_string_replace_search(vm, this, search, r); original: @@ -4099,7 +4495,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("valueOf"), - .value = njs_native_function(njs_string_prototype_value_of, 0, 0), + .value = njs_native_function(njs_string_prototype_value_of, 0), .writable = 1, .configurable = 1, }, @@ -4107,7 +4503,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toString"), - .value = njs_native_function(njs_string_prototype_to_string, 0, 0), + .value = njs_native_function(njs_string_prototype_to_string, 0), .writable = 1, .configurable = 1, }, @@ -4115,7 +4511,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("concat"), - .value = njs_native_function(njs_string_prototype_concat, 1, 0), + .value = njs_native_function(njs_string_prototype_concat, 1), .writable = 1, .configurable = 1, }, @@ -4123,8 +4519,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("fromUTF8"), - .value = njs_native_function(njs_string_prototype_from_utf8, 0, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_from_utf8, 0), .writable = 1, .configurable = 1, }, @@ -4132,8 +4527,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toUTF8"), - .value = njs_native_function(njs_string_prototype_to_utf8, 0, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_to_utf8, 0), .writable = 1, .configurable = 1, }, @@ -4141,8 +4535,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("fromBytes"), - .value = njs_native_function(njs_string_prototype_from_bytes, 0, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_from_bytes, 0), .writable = 1, .configurable = 1, }, @@ -4150,8 +4543,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toBytes"), - .value = njs_native_function(njs_string_prototype_to_bytes, 0, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_to_bytes, 0), .writable = 1, .configurable = 1, }, @@ -4159,8 +4551,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("slice"), - .value = njs_native_function(njs_string_prototype_slice, 2, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_slice, 2), .writable = 1, .configurable = 1, }, @@ -4168,8 +4559,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("substring"), - .value = njs_native_function(njs_string_prototype_substring, 2, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_substring, 2), .writable = 1, .configurable = 1, }, @@ -4177,8 +4567,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("substr"), - .value = njs_native_function(njs_string_prototype_substr, 2, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_substr, 2), .writable = 1, .configurable = 1, }, @@ -4186,8 +4575,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("charAt"), - .value = njs_native_function(njs_string_prototype_char_at, 1, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_char_at, 1), .writable = 1, .configurable = 1, }, @@ -4195,8 +4583,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("charCodeAt"), - .value = njs_native_function(njs_string_prototype_char_code_at, 1, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_char_code_at, 1), .writable = 1, .configurable = 1, }, @@ -4205,8 +4592,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("codePointAt"), - .value = njs_native_function(njs_string_prototype_char_code_at, 1, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_char_code_at, 1), .writable = 1, .configurable = 1, }, @@ -4214,8 +4600,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("indexOf"), - .value = njs_native_function(njs_string_prototype_index_of, 1, - NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_index_of, 1), .writable = 1, .configurable = 1, }, @@ -4223,8 +4608,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("lastIndexOf"), - .value = njs_native_function(njs_string_prototype_last_index_of, 1, - NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_NUMBER_ARG), + .value = njs_native_function(njs_string_prototype_last_index_of, 1), .writable = 1, .configurable = 1, }, @@ -4233,8 +4617,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("includes"), - .value = njs_native_function(njs_string_prototype_includes, 1, - NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_includes, 1), .writable = 1, .configurable = 1, }, @@ -4243,8 +4626,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("startsWith"), - .value = njs_native_function(njs_string_prototype_starts_with, 1, - NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_starts_with, 1), .writable = 1, .configurable = 1, }, @@ -4253,8 +4635,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("endsWith"), - .value = njs_native_function(njs_string_prototype_ends_with, 1, - NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_ends_with, 1), .writable = 1, .configurable = 1, }, @@ -4262,8 +4643,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toLowerCase"), - .value = njs_native_function(njs_string_prototype_to_lower_case, 0, - NJS_STRING_OBJECT_ARG), + .value = njs_native_function(njs_string_prototype_to_lower_case, 0), .writable = 1, .configurable = 1, }, @@ -4271,8 +4651,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("toUpperCase"), - .value = njs_native_function(njs_string_prototype_to_upper_case, 0, - NJS_STRING_OBJECT_ARG), + .value = njs_native_function(njs_string_prototype_to_upper_case, 0), .writable = 1, .configurable = 1, }, @@ -4280,8 +4659,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("trim"), - .value = njs_native_function(njs_string_prototype_trim, 0, - NJS_STRING_OBJECT_ARG), + .value = njs_native_function(njs_string_prototype_trim, 0), .writable = 1, .configurable = 1, }, @@ -4290,8 +4668,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("trimStart"), - .value = njs_native_function(njs_string_prototype_trim_start, 0, - NJS_STRING_OBJECT_ARG), + .value = njs_native_function(njs_string_prototype_trim_start, 0), .writable = 1, .configurable = 1, }, @@ -4300,8 +4677,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("trimEnd"), - .value = njs_native_function(njs_string_prototype_trim_end, 0, - NJS_STRING_OBJECT_ARG), + .value = njs_native_function(njs_string_prototype_trim_end, 0), .writable = 1, .configurable = 1, }, @@ -4310,8 +4686,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("repeat"), - .value = njs_native_function(njs_string_prototype_repeat, 1, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_repeat, 1), .writable = 1, .configurable = 1, }, @@ -4320,8 +4695,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("padStart"), - .value = njs_native_function(njs_string_prototype_pad_start, 1, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_string_prototype_pad_start, 1), .writable = 1, .configurable = 1, }, @@ -4330,8 +4704,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("padEnd"), - .value = njs_native_function(njs_string_prototype_pad_end, 1, - NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_STRING_ARG), + .value = njs_native_function(njs_string_prototype_pad_end, 1), .writable = 1, .configurable = 1, }, @@ -4339,8 +4712,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("search"), - .value = njs_native_function(njs_string_prototype_search, 1, - NJS_STRING_OBJECT_ARG, NJS_REGEXP_ARG), + .value = njs_native_function(njs_string_prototype_search, 1), .writable = 1, .configurable = 1, }, @@ -4348,8 +4720,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("match"), - .value = njs_native_function(njs_string_prototype_match, 1, - NJS_STRING_OBJECT_ARG, NJS_REGEXP_ARG), + .value = njs_native_function(njs_string_prototype_match, 1), .writable = 1, .configurable = 1, }, @@ -4357,8 +4728,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("split"), - .value = njs_native_function(njs_string_prototype_split, 2, - NJS_STRING_OBJECT_ARG, NJS_REGEXP_ARG, NJS_INTEGER_ARG), + .value = njs_native_function(njs_string_prototype_split, 2), .writable = 1, .configurable = 1, }, @@ -4366,8 +4736,7 @@ static const njs_object_prop_t njs_string_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("replace"), - .value = njs_native_function(njs_string_prototype_replace, 2, - NJS_STRING_OBJECT_ARG, NJS_REGEXP_ARG, NJS_FUNCTION_ARG), + .value = njs_native_function(njs_string_prototype_replace, 2), .writable = 1, .configurable = 1, }, @@ -4406,6 +4775,9 @@ njs_int_t njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_int_t ret; + njs_value_t *value; + static const uint32_t escape[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -4424,13 +4796,22 @@ njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - if (nargs > 1) { - return njs_string_encode(vm, &args[1], escape); + if (nargs < 2) { + njs_set_undefined(&vm->retval); + + return NJS_OK; } - vm->retval = njs_string_undefined; + value = njs_argument(args, 1); - return NJS_OK; + if (!njs_is_string(value)) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + return njs_string_encode(vm, value, escape); } @@ -4442,6 +4823,9 @@ njs_int_t njs_string_encode_uri_component(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_int_t ret; + njs_value_t *value; + static const uint32_t escape[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -4460,13 +4844,22 @@ njs_string_encode_uri_component(njs_vm_t *vm, njs_value_t *args, 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - if (nargs > 1) { - return njs_string_encode(vm, &args[1], escape); + if (nargs < 2) { + njs_set_undefined(&vm->retval); + + return NJS_OK; } - vm->retval = njs_string_undefined; + value = njs_argument(args, 1); - return NJS_OK; + if (!njs_is_string(value)) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + return njs_string_encode(vm, value, escape); } @@ -4537,6 +4930,9 @@ njs_int_t njs_string_decode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_int_t ret; + njs_value_t *value; + static const uint32_t reserve[] = { 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ @@ -4555,13 +4951,22 @@ njs_string_decode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ }; - if (nargs > 1) { - return njs_string_decode(vm, &args[1], reserve); + if (nargs < 2) { + njs_set_undefined(&vm->retval); + + return NJS_OK; } - vm->retval = njs_string_undefined; + value = njs_argument(args, 1); - return NJS_OK; + if (njs_slow_path(!njs_is_string(value))) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + return njs_string_decode(vm, value, reserve); } @@ -4573,6 +4978,9 @@ njs_int_t njs_string_decode_uri_component(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_int_t ret; + njs_value_t *value; + static const uint32_t reserve[] = { 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ @@ -4591,13 +4999,22 @@ njs_string_decode_uri_component(njs_vm_t *vm, njs_value_t *args, 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ }; - if (nargs > 1) { - return njs_string_decode(vm, &args[1], reserve); + if (nargs < 2) { + njs_set_undefined(&vm->retval); + + return NJS_OK; } - vm->retval = njs_string_undefined; + value = njs_argument(args, 1); - return NJS_OK; + if (njs_slow_path(!njs_is_string(value))) { + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + return njs_string_decode(vm, &args[1], reserve); } diff --git a/src/njs_value.c b/src/njs_value.c index cbca82f6..7f23f159 100644 --- a/src/njs_value.c +++ b/src/njs_value.c @@ -330,43 +330,6 @@ njs_type_string(njs_value_type_t type) } -const char * -njs_arg_type_string(uint8_t arg) -{ - switch (arg) { - case NJS_SKIP_ARG: - return "skip"; - - case NJS_NUMBER_ARG: - return "number"; - - case NJS_INTEGER_ARG: - return "integer"; - - case NJS_STRING_ARG: - return "string"; - - case NJS_OBJECT_ARG: - return "object"; - - case NJS_STRING_OBJECT_ARG: - return "string object"; - - case NJS_FUNCTION_ARG: - return "function"; - - case NJS_REGEXP_ARG: - return "regexp"; - - case NJS_DATE_ARG: - return "date"; - - default: - return "unknown"; - } -} - - void njs_value_undefined_set(njs_value_t *value) { diff --git a/src/njs_value.h b/src/njs_value.h index effeebdc..2a713618 100644 --- a/src/njs_value.h +++ b/src/njs_value.h @@ -235,12 +235,9 @@ typedef struct { } njs_closure_t; -#define NJS_ARGS_TYPES_MAX 5 - struct njs_function_s { njs_object_t object; - uint8_t args_types[NJS_ARGS_TYPES_MAX]; uint8_t args_offset; uint8_t args_count; @@ -391,14 +388,13 @@ typedef struct { } -#define njs_native_function(_function, _args_count, ...) { \ +#define njs_native_function(_function, _args_count) { \ .data = { \ .type = NJS_FUNCTION, \ .truth = 1, \ .u.function = & (njs_function_t) { \ .native = 1, \ .args_count = _args_count, \ - .args_types = { __VA_ARGS__ }, \ .args_offset = 1, \ .u.native = _function, \ .object = { .type = NJS_FUNCTION, \ @@ -827,7 +823,6 @@ njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, const njs_value_t *value, njs_object_enum_t kind, njs_bool_t all); njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, uint32_t *dest); const char *njs_type_string(njs_value_type_t type); -const char *njs_arg_type_string(uint8_t arg); njs_int_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst, const njs_value_t *src); diff --git a/src/test/njs_interactive_test.c b/src/test/njs_interactive_test.c index 41efac86..75bf97bd 100644 --- a/src/test/njs_interactive_test.c +++ b/src/test/njs_interactive_test.c @@ -144,7 +144,7 @@ static njs_interactive_test_t njs_test[] = { njs_str("function f(o) {return Object.keys(o)}" ENTER "f()" ENTER), - njs_str("TypeError: cannot convert undefined to object\n" + njs_str("TypeError: cannot convert undefined argument to object\n" " at Object.keys (native)\n" " at f (:1)\n" " at main (native)\n") }, diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 59b538d8..c929b3e2 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -1492,6 +1492,9 @@ static njs_unit_test_t njs_test[] = { njs_str("'1' == new Number(1)"), njs_str("true") }, + { njs_str("new Number(null) + ''"), + njs_str("0") }, + { njs_str("new String('abc') == 'abc'"), njs_str("true") }, @@ -11419,6 +11422,9 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = Object.freeze({a:1}); Object.isFrozen(o)"), njs_str("true") }, + { njs_str("Object.isFrozen(undefined)"), + njs_str("true") }, + { njs_str("var o = Object.seal({a:1}); o.a = 2; o.a"), njs_str("2") }, @@ -11443,6 +11449,9 @@ static njs_unit_test_t njs_test[] = { njs_str("Object.seal('')"), njs_str("") }, + { njs_str("Object.seal(undefined)"), + njs_str("undefined") }, + { njs_str("Object.isSealed({a:1})"), njs_str("false") }, @@ -11559,6 +11568,9 @@ static njs_unit_test_t njs_test[] = { njs_str("Object.isExtensible(Object.freeze([]))"), njs_str("false") }, + { njs_str("Object.isExtensible(undefined)"), + njs_str("false") }, + { njs_str( "var fail;" "function isConfigurableMethods(o) {" @@ -13246,6 +13258,12 @@ static njs_unit_test_t njs_test[] = { njs_str("1/parseInt('-0')"), njs_str("-Infinity") }, + { njs_str("parseInt('11', new Number(Infinity)) === parseInt('11', Infinity)"), + njs_str("true") }, + + { njs_str("parseInt('11', Number.POSITIVE_INFINITY)"), + njs_str("11") }, + { njs_str("parseFloat.name"), njs_str("parseFloat") },