diff --git a/docs/09.EXT-REFERENCE-ARG.md b/docs/09.EXT-REFERENCE-ARG.md index 8884420b9..bac1a6173 100644 --- a/docs/09.EXT-REFERENCE-ARG.md +++ b/docs/09.EXT-REFERENCE-ARG.md @@ -122,6 +122,42 @@ Enum that indicates whether an argument is optional or required. - [jerryx_arg_function](#jerryx_arg_function) - [jerryx_arg_native_pointer](#jerryx_arg_native_pointer) +## jerryx_arg_round_t + +Enum that indicates the rounding policy which will be chosen to transform an integer. + + - JERRYX_ARG_ROUND - use round() method. + - JERRYX_ARG_FLOOR - use floor() method. + - JERRYX_ARG_CEIL - use ceil() method. + +**See also** + +- [jerryx_arg_uint8](#jerryx_arg_uint8) +- [jerryx_arg_uint16](#jerryx_arg_uint16) +- [jerryx_arg_uint32](#jerryx_arg_uint32) +- [jerryx_arg_int8](#jerryx_arg_int8) +- [jerryx_arg_int16](#jerryx_arg_int16) +- [jerryx_arg_int32](#jerryx_arg_int32) + + +## jerryx_arg_clamp_t + + Indicates the clamping policy which will be chosen to transform an integer. + If the policy is NO_CLAMP, and the number is out of range, + then the transformer will throw a range error. + + - JERRYX_ARG_CLAMP - clamp the number when it is out of range + - JERRYX_ARG_NO_CLAMP - throw a range error + +**See also** + +- [jerryx_arg_uint8](#jerryx_arg_uint8) +- [jerryx_arg_uint16](#jerryx_arg_uint16) +- [jerryx_arg_uint32](#jerryx_arg_uint32) +- [jerryx_arg_int8](#jerryx_arg_int8) +- [jerryx_arg_int16](#jerryx_arg_int16) +- [jerryx_arg_int32](#jerryx_arg_int32) + # Main functions ## jerryx_arg_transform_this_and_args @@ -270,6 +306,49 @@ jerryx_arg_transform_object_properties (const jerry_value_t obj_val, # Helpers for commonly used validations +## jerryx_arg_uint8 + +## jerryx_arg_uint16 + +## jerryx_arg_uint32 + +## jerryx_arg_int8 + +## jerryx_arg_int16 + +## jerryx_arg_int32 + +**Summary** + +All above jerryx_arg_[u]intX functions are used to create a validation/transformation step +(`jerryx_arg_t`) that expects to consume one `number` JS argument +and stores it into a C integer (uint8, int8, uint16, ...) + +**Prototype** + +Take jerryx_arg_int32 as an example + +```c +static inline jerryx_arg_t +jerryx_arg_int32 (int32_t *dest, + jerryx_arg_round_t round_flag, + jerryx_arg_clamp_t clamp_flag, + jerryx_arg_coerce_t coerce_flag, + jerryx_arg_optional_t opt_flag); +``` + + - return value - the created `jerryx_arg_t` instance. + - `dest` - pointer to the `int32_t` where the result should be stored. + - `round_flag` - the rounding policy. + - `clamp_flag` - the clamping policy. + - `coerce_flag` - whether type coercion is allowed. + - `opt_flag` - whether the argument is optional. + +**See also** + +- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args) + + ## jerryx_arg_number **Summary** diff --git a/jerry-ext/arg/arg-transform-functions.c b/jerry-ext/arg/arg-transform-functions.c index b51c4b5ca..f31fa4adb 100644 --- a/jerry-ext/arg/arg-transform-functions.c +++ b/jerry-ext/arg/arg-transform-functions.c @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "jerryscript-ext/arg.h" #include "jerryscript.h" @@ -39,14 +41,15 @@ jerryx_arg_transform_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< ava } /* jerryx_arg_transform_optional */ /** - * Tranform a JS argument to a double. Type coercion is not allowed. + * The common part in transforming a JS argument to a number (double or certain int) type. + * Type coercion is not allowed. * * @return jerry undefined: the transformer passes, * jerry error: the transformer fails. */ -jerry_value_t -jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */ - const jerryx_arg_t *c_arg_p) /**< the native arg */ +static jerry_value_t +jerryx_arg_transform_number_strict_common (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */ + double *number_p) /**< [out] the number in JS arg */ { jerry_value_t js_arg = jerryx_arg_js_iterator_pop (js_arg_iter_p); @@ -56,21 +59,21 @@ jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, /** (jerry_char_t *) "It is not a number."); } - double *dest = c_arg_p->dest; - *dest = jerry_get_number_value (js_arg); + *number_p = jerry_get_number_value (js_arg); return jerry_create_undefined (); -} /* jerryx_arg_transform_number_strict */ +} /* jerryx_arg_transform_number_strict_common */ /** - * Transform a JS argument to a double. Type coercion is allowed. + * The common part in transforming a JS argument to a number (double or certain int) type. + * Type coercion is allowed. * * @return jerry undefined: the transformer passes, * jerry error: the transformer fails. */ -jerry_value_t -jerryx_arg_transform_number (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */ - const jerryx_arg_t *c_arg_p) /**< the native arg */ +static jerry_value_t +jerryx_arg_transform_number_common (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */ + double *number_p) /**< [out] the number in JS arg */ { jerry_value_t js_arg = jerryx_arg_js_iterator_pop (js_arg_iter_p); @@ -84,13 +87,118 @@ jerryx_arg_transform_number (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< avail (jerry_char_t *) "It can not be converted to a number."); } - double *dest = c_arg_p->dest; - *dest = jerry_get_number_value (to_number); + *number_p = jerry_get_number_value (to_number); jerry_release_value (to_number); return jerry_create_undefined (); +} /* jerryx_arg_transform_number_common */ + +/** + * Transform a JS argument to a double. Type coercion is not allowed. + * + * @return jerry undefined: the transformer passes, + * jerry error: the transformer fails. + */ +jerry_value_t +jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */ + const jerryx_arg_t *c_arg_p) /**< the native arg */ +{ + return jerryx_arg_transform_number_strict_common (js_arg_iter_p, c_arg_p->dest); +} /* jerryx_arg_transform_number_strict */ + +/** + * Tranform a JS argument to a double. Type coercion is allowed. + * + * @return jerry undefined: the transformer passes, + * jerry error: the transformer fails. + */ +jerry_value_t +jerryx_arg_transform_number (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< available JS args */ + const jerryx_arg_t *c_arg_p) /**< the native arg */ +{ + return jerryx_arg_transform_number_common (js_arg_iter_p, c_arg_p->dest); } /* jerryx_arg_transform_number */ +/** + * Helper function to process a double number before converting it + * to an integer. + * + * @return jerry undefined: the transformer passes, + * jerry error: the transformer fails. + */ +static jerry_value_t +jerryx_arg_helper_process_double (double *d, /**< [in, out] the number to be processed */ + double min, /**< the min value for clamping */ + double max, /**< the max value for clamping */ + jerryx_arg_int_option_t option) /**< the converting policies */ +{ + if (option.clamp == JERRYX_ARG_NO_CLAMP) + { + if (*d > max || *d < min) + { + return jerry_create_error (JERRY_ERROR_TYPE, + (jerry_char_t *) "The number is out of range."); + } + } + else + { + *d = *d < min ? min : *d; + *d = *d > max ? max : *d; + } + + if (option.round == JERRYX_ARG_ROUND) + { + *d = (*d >= 0.0) ? floor (*d + 0.5) : ceil (*d - 0.5); + } + else if (option.round == JERRYX_ARG_FLOOR) + { + *d = floor (*d); + } + else + { + *d = ceil (*d); + } + + return jerry_create_undefined (); +} /* jerryx_arg_helper_process_double */ + +/** + * Use the macro to define thr transform functions for int type. + */ +#define JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE(type, suffix, min, max) \ + jerry_value_t jerryx_arg_transform_ ## type ## suffix (jerryx_arg_js_iterator_t *js_arg_iter_p, \ + const jerryx_arg_t *c_arg_p) \ + { \ + double tmp; \ + jerry_value_t rv = jerryx_arg_transform_number ## suffix ## _common (js_arg_iter_p, &tmp); \ + if (jerry_value_has_error_flag (rv)) \ + { \ + return rv; \ + } \ + jerry_release_value (rv); \ + jerryx_arg_int_option_t *options_p = (jerryx_arg_int_option_t *) &c_arg_p->extra_info; \ + rv = jerryx_arg_helper_process_double (&tmp, min, max, *options_p); \ + if (jerry_value_has_error_flag (rv)) \ + { \ + return rv; \ + } \ + *(type ## _t *) c_arg_p->dest = (type ## _t) tmp; \ + return rv; \ + } + +#define JERRYX_ARG_TRANSFORM_FUNC_FOR_INT(type, min, max) \ + JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE (type, _strict, min, max) \ + JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE (type, , min, max) + +JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (uint8, 0, UINT8_MAX) +JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (int8, INT8_MIN, INT8_MAX) +JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (uint16, 0, UINT16_MAX) +JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (int16, INT16_MIN, INT16_MAX) +JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (uint32, 0, UINT32_MAX) +JERRYX_ARG_TRANSFORM_FUNC_FOR_INT (int32, INT32_MIN, INT32_MAX) + +#undef JERRYX_ARG_TRANSFORM_FUNC_FOR_INT_TEMPLATE +#undef JERRYX_ARG_TRANSFORM_FUNC_FOR_INT /** * Tranform a JS argument to a boolean. Type coercion is not allowed. * @@ -294,12 +402,12 @@ jerryx_arg_transform_object_props (jerryx_arg_js_iterator_t *js_arg_iter_p, /**< * Define transformer for optional argument. */ #define JERRYX_ARG_TRANSFORM_OPTIONAL(type) \ -jerry_value_t \ -jerryx_arg_transform_ ## type ## _optional (jerryx_arg_js_iterator_t *js_arg_iter_p, \ - const jerryx_arg_t *c_arg_p) \ -{ \ - return jerryx_arg_transform_optional (js_arg_iter_p, c_arg_p, jerryx_arg_transform_ ## type); \ -} + jerry_value_t \ + jerryx_arg_transform_ ## type ## _optional (jerryx_arg_js_iterator_t *js_arg_iter_p, \ + const jerryx_arg_t *c_arg_p) \ + { \ + return jerryx_arg_transform_optional (js_arg_iter_p, c_arg_p, jerryx_arg_transform_ ## type); \ + } JERRYX_ARG_TRANSFORM_OPTIONAL (number) JERRYX_ARG_TRANSFORM_OPTIONAL (number_strict) @@ -311,6 +419,21 @@ JERRYX_ARG_TRANSFORM_OPTIONAL (function) JERRYX_ARG_TRANSFORM_OPTIONAL (native_pointer) JERRYX_ARG_TRANSFORM_OPTIONAL (object_props) +JERRYX_ARG_TRANSFORM_OPTIONAL (uint8) +JERRYX_ARG_TRANSFORM_OPTIONAL (uint16) +JERRYX_ARG_TRANSFORM_OPTIONAL (uint32) +JERRYX_ARG_TRANSFORM_OPTIONAL (int8) +JERRYX_ARG_TRANSFORM_OPTIONAL (int16) +JERRYX_ARG_TRANSFORM_OPTIONAL (int32) +JERRYX_ARG_TRANSFORM_OPTIONAL (int8_strict) +JERRYX_ARG_TRANSFORM_OPTIONAL (int16_strict) +JERRYX_ARG_TRANSFORM_OPTIONAL (int32_strict) +JERRYX_ARG_TRANSFORM_OPTIONAL (uint8_strict) +JERRYX_ARG_TRANSFORM_OPTIONAL (uint16_strict) +JERRYX_ARG_TRANSFORM_OPTIONAL (uint32_strict) + +#undef JERRYX_ARG_TRANSFORM_OPTIONAL + /** * Ignore the JS argument. * diff --git a/jerry-ext/arg/arg.c b/jerry-ext/arg/arg.c index 3acac7d5f..9c932e124 100644 --- a/jerry-ext/arg/arg.c +++ b/jerry-ext/arg/arg.c @@ -17,6 +17,15 @@ #include "jerryscript-ext/arg.h" #include "jerryscript.h" + +#define JERRYX_STATIC_ASSERT(x, msg) \ + enum { static_assertion_failed_ ## msg = 1 / (!!(x)) } + +JERRYX_STATIC_ASSERT (sizeof (jerryx_arg_int_option_t) <= sizeof (((jerryx_arg_t *) 0)->extra_info), + jerryx_arg_number_options_t_must_fit_into_extra_info); + +#undef JERRYX_STATIC_ASSERT + /** * Validate the JS arguments and assign them to the native arguments. * diff --git a/jerry-ext/include/jerryscript-ext/arg.h b/jerry-ext/include/jerryscript-ext/arg.h index b890e910d..03424c378 100644 --- a/jerry-ext/include/jerryscript-ext/arg.h +++ b/jerry-ext/include/jerryscript-ext/arg.h @@ -106,13 +106,52 @@ typedef enum JERRYX_ARG_REQUIRED } jerryx_arg_optional_t; +/** + * Indicates the rounding policy which will be chosen to transform an integer. + */ +typedef enum +{ + JERRYX_ARG_ROUND, /**< round */ + JERRYX_ARG_FLOOR, /**< floor */ + JERRYX_ARG_CEIL /**< ceil */ +} jerryx_arg_round_t; + +/** + * Indicates the clamping policy which will be chosen to transform an integer. + * If the policy is NO_CLAMP, and the number is out of range, + * then the transformer will throw a range error. + */ +typedef enum +{ + JERRYX_ARG_CLAMP,/**< clamp the number when it is out of range */ + JERRYX_ARG_NO_CLAMP /**< throw a range error */ +} jerryx_arg_clamp_t; + /* Inline functions for initializing jerryx_arg_t */ + +#define JERRYX_ARG_INTEGER(type) \ + static inline jerryx_arg_t \ + jerryx_arg_ ## type (type ## _t *dest, \ + jerryx_arg_round_t round_flag, \ + jerryx_arg_clamp_t clamp_flag, \ + jerryx_arg_coerce_t coerce_flag, \ + jerryx_arg_optional_t opt_flag); + +JERRYX_ARG_INTEGER (uint8) +JERRYX_ARG_INTEGER (int8) +JERRYX_ARG_INTEGER (uint16) +JERRYX_ARG_INTEGER (int16) +JERRYX_ARG_INTEGER (uint32) +JERRYX_ARG_INTEGER (int32) + +#undef JERRYX_ARG_INTEGER + static inline jerryx_arg_t -jerryx_arg_number (double *dest, jerryx_arg_coerce_t conv_flag, jerryx_arg_optional_t opt_flag); +jerryx_arg_number (double *dest, jerryx_arg_coerce_t coerce_flag, jerryx_arg_optional_t opt_flag); static inline jerryx_arg_t -jerryx_arg_boolean (bool *dest, jerryx_arg_coerce_t conv_flag, jerryx_arg_optional_t opt_flag); +jerryx_arg_boolean (bool *dest, jerryx_arg_coerce_t coerce_flag, jerryx_arg_optional_t opt_flag); static inline jerryx_arg_t -jerryx_arg_string (char *dest, uint32_t size, jerryx_arg_coerce_t conv_flag, jerryx_arg_optional_t opt_flag); +jerryx_arg_string (char *dest, uint32_t size, jerryx_arg_coerce_t coerce_flag, jerryx_arg_optional_t opt_flag); static inline jerryx_arg_t jerryx_arg_function (jerry_value_t *dest, jerryx_arg_optional_t opt_flag); static inline jerryx_arg_t diff --git a/jerry-ext/include/jerryscript-ext/arg.impl.h b/jerry-ext/include/jerryscript-ext/arg.impl.h index 0a1e5482e..874ed0fd1 100644 --- a/jerry-ext/include/jerryscript-ext/arg.impl.h +++ b/jerry-ext/include/jerryscript-ext/arg.impl.h @@ -17,44 +17,98 @@ #define JERRYX_ARG_IMPL_H /* transform functions for each type. */ -jerry_value_t jerryx_arg_transform_number_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_number_strict_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_number_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_number (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_boolean_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_boolean_strict_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_boolean_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_boolean (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_string_strict (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_string_strict_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_string_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_string (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_function (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_function_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_native_pointer (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_native_pointer_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, + +#define JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL(type) \ + jerry_value_t jerryx_arg_transform_ ## type (jerryx_arg_js_iterator_t *js_arg_iter_p, \ + const jerryx_arg_t *c_arg_p); \ + jerry_value_t jerryx_arg_transform_ ## type ## _optional (jerryx_arg_js_iterator_t *js_arg_iter_p, \ const jerryx_arg_t *c_arg_p); + +#define JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT(type) \ + JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL (type) \ + JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL (type ## _strict) + +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (uint8) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (int8) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (uint16) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (int16) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (uint32) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (int32) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (number) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (string) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT (boolean) + +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL (function) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL (native_pointer) +JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL (object_props) + jerry_value_t jerryx_arg_transform_ignore (jerryx_arg_js_iterator_t *js_arg_iter_p, const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_object_props (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); -jerry_value_t jerryx_arg_transform_object_props_optional (jerryx_arg_js_iterator_t *js_arg_iter_p, - const jerryx_arg_t *c_arg_p); + +#undef JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL +#undef JERRYX_ARG_TRANSFORM_FUNC_WITH_OPTIONAL_AND_STRICT + +/** + * The structure indicates the options used to transform integer argument. + * It will be passed into jerryx_arg_t's extra_info field. + */ +typedef struct +{ + uint8_t round; /**< rounding policy */ + uint8_t clamp; /**< clamping policy */ +} jerryx_arg_int_option_t; + +/** + * The macro used to generate jerryx_arg_xxx for int type. + */ +#define JERRYX_ARG_INT(type) \ + static inline jerryx_arg_t \ + jerryx_arg_ ## type (type ## _t *dest, \ + jerryx_arg_round_t round_flag, \ + jerryx_arg_clamp_t clamp_flag, \ + jerryx_arg_coerce_t coerce_flag, \ + jerryx_arg_optional_t opt_flag) \ + { \ + jerryx_arg_transform_func_t func; \ + if (coerce_flag == JERRYX_ARG_NO_COERCE) \ + { \ + if (opt_flag == JERRYX_ARG_OPTIONAL) \ + { \ + func = jerryx_arg_transform_ ## type ## _strict_optional; \ + } \ + else \ + { \ + func = jerryx_arg_transform_ ## type ## _strict; \ + } \ + } \ + else \ + { \ + if (opt_flag == JERRYX_ARG_OPTIONAL) \ + { \ + func = jerryx_arg_transform_ ## type ## _optional; \ + } \ + else \ + { \ + func = jerryx_arg_transform_ ## type; \ + } \ + } \ + const jerryx_arg_int_option_t int_option = { .round = round_flag, .clamp = clamp_flag }; \ + return (jerryx_arg_t) \ + { \ + .func = func, \ + .dest = (void *) dest, \ + .extra_info = *(uintptr_t *) &int_option \ + }; \ + } + +JERRYX_ARG_INT (uint8) +JERRYX_ARG_INT (int8) +JERRYX_ARG_INT (uint16) +JERRYX_ARG_INT (int16) +JERRYX_ARG_INT (uint32) +JERRYX_ARG_INT (int32) + +#undef JERRYX_ARG_INT /** * Create a validation/transformation step (`jerryx_arg_t`) that expects to diff --git a/tests/unit-ext/test-ext-arg.c b/tests/unit-ext/test-ext-arg.c index 06c31b730..b9bcab50c 100644 --- a/tests/unit-ext/test-ext-arg.c +++ b/tests/unit-ext/test-ext-arg.c @@ -50,6 +50,9 @@ const char *test_source = ( " get: function() { throw new TypeError('prop2 error') }" "});" "test_validator_prop3(obj2);" + "test_validator_int1(-1000, 1000, 128, -1000, 1000, -127," + " -1000, 4294967297, 65536, -2200000000, 4294967297, -2147483647);" + "test_validator_int2(-1.5, -1.5, -1.5, 1.5, 1.5, 1.5, 300.5, 300.5);" ); static const jerry_object_native_info_t thing_a_info = @@ -77,6 +80,7 @@ static my_type_b_t my_thing_b; static int validator1_count = 0; static int validator2_count = 0; +static int validator_int_count = 0; static int validator_prop_count = 0; @@ -144,7 +148,7 @@ test_validator1_handler (const jerry_value_t func_obj_val __attribute__((unused) jerry_release_value (is_ok); jerry_release_value (arg4); - validator1_count ++; + validator1_count++; return jerry_create_undefined (); } /* test_validator1_handler */ @@ -218,7 +222,7 @@ test_validator2_handler (const jerry_value_t func_obj_val __attribute__((unused) } jerry_release_value (is_ok); - validator2_count ++; + validator2_count++; return jerry_create_undefined (); } /* test_validator2_handler */ @@ -256,7 +260,7 @@ test_validator_prop1_handler (const jerry_value_t func_obj_val __attribute__((un TEST_ASSERT (native2 == 1.5); TEST_ASSERT (native3 == 3); - validator_prop_count ++; + validator_prop_count++; return jerry_create_undefined (); } /* test_validator_prop1_handler */ @@ -308,7 +312,7 @@ test_validator_prop2_handler (const jerry_value_t func_obj_val __attribute__((un TEST_ASSERT (native3 == 3); } - validator_prop_count ++; + validator_prop_count++; return jerry_create_undefined (); } /* test_validator_prop2_handler */ @@ -340,12 +344,110 @@ test_validator_prop3_handler (const jerry_value_t func_obj_val __attribute__((un TEST_ASSERT (!native1); TEST_ASSERT (native2); - validator_prop_count ++; + validator_prop_count++; jerry_release_value (is_ok); return jerry_create_undefined (); } /* test_validator_prop3_handler */ +/* + * args_p[0-2] are uint8, args_p[3-5] are int8, args_p[6-8] are uint32, args_p[9-11] are int32. + */ +static jerry_value_t +test_validator_int1_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */ + const jerry_value_t this_val __attribute__((unused)), /**< this value */ + const jerry_value_t args_p[], /**< arguments list */ + const jerry_length_t args_cnt) /**< arguments length */ +{ + uint8_t num0, num1, num2; + int8_t num3, num4, num5; + uint32_t num6, num7, num8; + int32_t num9, num10, num11; + + jerryx_arg_t mapping[] = + { + jerryx_arg_uint8 (&num0, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_uint8 (&num1, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_uint8 (&num2, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num3, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num4, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num5, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_uint32 (&num6, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_uint32 (&num7, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_uint32 (&num8, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int32 (&num9, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int32 (&num10, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int32 (&num11, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED) + }; + + jerry_value_t is_ok = jerryx_arg_transform_args (args_p, + args_cnt, + mapping, + 12); + + TEST_ASSERT (!jerry_value_has_error_flag (is_ok)); + TEST_ASSERT (num0 == 0); + TEST_ASSERT (num1 == 255); + TEST_ASSERT (num2 == 128); + TEST_ASSERT (num3 == -128); + TEST_ASSERT (num4 == 127); + TEST_ASSERT (num5 == -127); + TEST_ASSERT (num6 == 0); + TEST_ASSERT (num7 == 4294967295); + TEST_ASSERT (num8 == 65536); + TEST_ASSERT (num9 == -2147483648); + TEST_ASSERT (num10 == 2147483647); + TEST_ASSERT (num11 == -2147483647); + + jerry_release_value (is_ok); + validator_int_count++; + + return jerry_create_undefined (); +} /* test_validator_int1_handler */ + +static jerry_value_t +test_validator_int2_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */ + const jerry_value_t this_val __attribute__((unused)), /**< this value */ + const jerry_value_t args_p[], /**< arguments list */ + const jerry_length_t args_cnt) /**< arguments length */ +{ + int8_t num0, num1, num2, num3, num4, num5, num6, num7; + num6 = 123; + num7 = 123; + + jerryx_arg_t mapping[] = + { + jerryx_arg_int8 (&num0, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num1, JERRYX_ARG_FLOOR, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num2, JERRYX_ARG_CEIL, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num3, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num4, JERRYX_ARG_FLOOR, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num5, JERRYX_ARG_CEIL, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num6, JERRYX_ARG_ROUND, JERRYX_ARG_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + jerryx_arg_int8 (&num7, JERRYX_ARG_ROUND, JERRYX_ARG_NO_CLAMP, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED), + }; + + jerry_value_t is_ok = jerryx_arg_transform_args (args_p, + args_cnt, + mapping, + 8); + + TEST_ASSERT (jerry_value_has_error_flag (is_ok)); + TEST_ASSERT (num0 == -2); + TEST_ASSERT (num1 == -2); + TEST_ASSERT (num2 == -1); + TEST_ASSERT (num3 == 2); + TEST_ASSERT (num4 == 1); + TEST_ASSERT (num5 == 2); + TEST_ASSERT (num6 == 127); + TEST_ASSERT (num7 == 123); + + jerry_release_value (is_ok); + validator_int_count++; + + return jerry_create_undefined (); +} /* test_validator_int2_handler */ + static jerry_value_t create_object_a_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */ const jerry_value_t this_val, /**< this value */ @@ -405,6 +507,8 @@ main (void) register_js_function ("test_validator1", test_validator1_handler); register_js_function ("test_validator2", test_validator2_handler); + register_js_function ("test_validator_int1", test_validator_int1_handler); + register_js_function ("test_validator_int2", test_validator_int2_handler); register_js_function ("MyObjectA", create_object_a_handler); register_js_function ("MyObjectB", create_object_b_handler); register_js_function ("test_validator_prop1", test_validator_prop1_handler); @@ -419,6 +523,7 @@ main (void) TEST_ASSERT (validator1_count == 4); TEST_ASSERT (validator2_count == 3); TEST_ASSERT (validator_prop_count == 4); + TEST_ASSERT (validator_int_count == 2); jerry_release_value (res); jerry_release_value (parsed_code_val);