1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "arg-internal.h" 17425bb815Sopenharmony_ci#include "jerryscript-ext/arg.h" 18425bb815Sopenharmony_ci#include "jerryscript.h" 19425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 20425bb815Sopenharmony_ci#include "jerryscript-core.h" 21425bb815Sopenharmony_ci#endif 22425bb815Sopenharmony_ci 23425bb815Sopenharmony_ci#define JERRYX_STATIC_ASSERT(x, msg) \ 24425bb815Sopenharmony_ci enum { static_assertion_failed_ ## msg = 1 / (!!(x)) } 25425bb815Sopenharmony_ci 26425bb815Sopenharmony_ciJERRYX_STATIC_ASSERT (sizeof (jerryx_arg_int_option_t) <= sizeof (((jerryx_arg_t *) 0)->extra_info), 27425bb815Sopenharmony_ci jerryx_arg_number_options_t_must_fit_into_extra_info); 28425bb815Sopenharmony_ci 29425bb815Sopenharmony_ci#undef JERRYX_STATIC_ASSERT 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_ci/** 32425bb815Sopenharmony_ci * Validate the JS arguments and assign them to the native arguments. 33425bb815Sopenharmony_ci * 34425bb815Sopenharmony_ci * @return jerry undefined: all validators passed, 35425bb815Sopenharmony_ci * jerry error: a validator failed. 36425bb815Sopenharmony_ci */ 37425bb815Sopenharmony_cijerry_value_t 38425bb815Sopenharmony_cijerryx_arg_transform_args (const jerry_value_t *js_arg_p, /**< points to the array with JS arguments */ 39425bb815Sopenharmony_ci const jerry_length_t js_arg_cnt, /**< the count of the `js_arg_p` array */ 40425bb815Sopenharmony_ci const jerryx_arg_t *c_arg_p, /**< points to the array of validation/transformation steps */ 41425bb815Sopenharmony_ci jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 42425bb815Sopenharmony_ci{ 43425bb815Sopenharmony_ci jerry_value_t ret = jerry_create_undefined (); 44425bb815Sopenharmony_ci 45425bb815Sopenharmony_ci jerryx_arg_js_iterator_t iterator = 46425bb815Sopenharmony_ci { 47425bb815Sopenharmony_ci .js_arg_p = js_arg_p, 48425bb815Sopenharmony_ci .js_arg_cnt = js_arg_cnt, 49425bb815Sopenharmony_ci .js_arg_idx = 0 50425bb815Sopenharmony_ci }; 51425bb815Sopenharmony_ci 52425bb815Sopenharmony_ci for (; c_arg_cnt != 0 && !jerry_value_is_error (ret); c_arg_cnt--, c_arg_p++) 53425bb815Sopenharmony_ci { 54425bb815Sopenharmony_ci ret = c_arg_p->func (&iterator, c_arg_p); 55425bb815Sopenharmony_ci } 56425bb815Sopenharmony_ci 57425bb815Sopenharmony_ci return ret; 58425bb815Sopenharmony_ci} /* jerryx_arg_transform_args */ 59425bb815Sopenharmony_ci 60425bb815Sopenharmony_ci/** 61425bb815Sopenharmony_ci * Validate the this value and the JS arguments, 62425bb815Sopenharmony_ci * and assign them to the native arguments. 63425bb815Sopenharmony_ci * This function is useful to perform input validation inside external 64425bb815Sopenharmony_ci * function handlers (see jerry_external_handler_t). 65425bb815Sopenharmony_ci * @note this_val is processed as the first value, before the array of arguments. 66425bb815Sopenharmony_ci * 67425bb815Sopenharmony_ci * @return jerry undefined: all validators passed, 68425bb815Sopenharmony_ci * jerry error: a validator failed. 69425bb815Sopenharmony_ci */ 70425bb815Sopenharmony_cijerry_value_t 71425bb815Sopenharmony_cijerryx_arg_transform_this_and_args (const jerry_value_t this_val, /**< the this_val for the external function */ 72425bb815Sopenharmony_ci const jerry_value_t *js_arg_p, /**< points to the array with JS arguments */ 73425bb815Sopenharmony_ci const jerry_length_t js_arg_cnt, /**< the count of the `js_arg_p` array */ 74425bb815Sopenharmony_ci const jerryx_arg_t *c_arg_p, /**< points to the array of transformation steps */ 75425bb815Sopenharmony_ci jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 76425bb815Sopenharmony_ci{ 77425bb815Sopenharmony_ci if (c_arg_cnt == 0) 78425bb815Sopenharmony_ci { 79425bb815Sopenharmony_ci return jerry_create_undefined (); 80425bb815Sopenharmony_ci } 81425bb815Sopenharmony_ci 82425bb815Sopenharmony_ci jerryx_arg_js_iterator_t iterator = 83425bb815Sopenharmony_ci { 84425bb815Sopenharmony_ci .js_arg_p = &this_val, 85425bb815Sopenharmony_ci .js_arg_cnt = 1, 86425bb815Sopenharmony_ci .js_arg_idx = 0 87425bb815Sopenharmony_ci }; 88425bb815Sopenharmony_ci 89425bb815Sopenharmony_ci jerry_value_t ret = c_arg_p->func (&iterator, c_arg_p); 90425bb815Sopenharmony_ci 91425bb815Sopenharmony_ci if (jerry_value_is_error (ret)) 92425bb815Sopenharmony_ci { 93425bb815Sopenharmony_ci jerry_release_value (ret); 94425bb815Sopenharmony_ci 95425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "'this' validation failed."); 96425bb815Sopenharmony_ci } 97425bb815Sopenharmony_ci 98425bb815Sopenharmony_ci return jerryx_arg_transform_args (js_arg_p, js_arg_cnt, c_arg_p + 1, c_arg_cnt - 1); 99425bb815Sopenharmony_ci} /* jerryx_arg_transform_this_and_args */ 100425bb815Sopenharmony_ci 101425bb815Sopenharmony_ci/** 102425bb815Sopenharmony_ci * Validate the `obj_val`'s properties, 103425bb815Sopenharmony_ci * and assign them to the native arguments. 104425bb815Sopenharmony_ci * 105425bb815Sopenharmony_ci * @return jerry undefined: all validators passed, 106425bb815Sopenharmony_ci * jerry error: a validator failed. 107425bb815Sopenharmony_ci */ 108425bb815Sopenharmony_cijerry_value_t 109425bb815Sopenharmony_cijerryx_arg_transform_object_properties (const jerry_value_t obj_val,/**< the JS object */ 110425bb815Sopenharmony_ci const jerry_char_t **name_p, /**< property name list of the JS object */ 111425bb815Sopenharmony_ci const jerry_length_t name_cnt, /**< count of the name list */ 112425bb815Sopenharmony_ci const jerryx_arg_t *c_arg_p, /**< points to the array of transformation steps */ 113425bb815Sopenharmony_ci jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 114425bb815Sopenharmony_ci{ 115425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 116425bb815Sopenharmony_ci jerry_value_t* prop; 117425bb815Sopenharmony_ci jerry_value_t prop_i; 118425bb815Sopenharmony_ci#endif 119425bb815Sopenharmony_ci if (!jerry_value_is_object (obj_val)) 120425bb815Sopenharmony_ci { 121425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "Not an object."); 122425bb815Sopenharmony_ci } 123425bb815Sopenharmony_ci 124425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 125425bb815Sopenharmony_ci prop = (jerry_value_t*) jerry_vla_malloc (sizeof(jerry_value_t) * name_cnt); 126425bb815Sopenharmony_ci if (!prop) 127425bb815Sopenharmony_ci { 128425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "malloc prop fail."); 129425bb815Sopenharmony_ci } 130425bb815Sopenharmony_ci#else 131425bb815Sopenharmony_ci JERRY_VLA (jerry_value_t, prop, name_cnt); 132425bb815Sopenharmony_ci#endif 133425bb815Sopenharmony_ci for (jerry_length_t i = 0; i < name_cnt; i++, name_p++) 134425bb815Sopenharmony_ci { 135425bb815Sopenharmony_ci const jerry_value_t name_str = jerry_create_string (*name_p); 136425bb815Sopenharmony_ci prop[i] = jerry_get_property (obj_val, name_str); 137425bb815Sopenharmony_ci jerry_release_value (name_str); 138425bb815Sopenharmony_ci 139425bb815Sopenharmony_ci if (jerry_value_is_error (prop[i])) 140425bb815Sopenharmony_ci { 141425bb815Sopenharmony_ci for (jerry_length_t j = 0; j < i; j++) 142425bb815Sopenharmony_ci { 143425bb815Sopenharmony_ci jerry_release_value (prop[j]); 144425bb815Sopenharmony_ci } 145425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 146425bb815Sopenharmony_ci prop_i = prop[i]; 147425bb815Sopenharmony_ci jerry_vla_free ((char*)prop); 148425bb815Sopenharmony_ci return prop_i; 149425bb815Sopenharmony_ci#else 150425bb815Sopenharmony_ci return prop[i]; 151425bb815Sopenharmony_ci#endif 152425bb815Sopenharmony_ci } 153425bb815Sopenharmony_ci } 154425bb815Sopenharmony_ci 155425bb815Sopenharmony_ci const jerry_value_t ret = jerryx_arg_transform_args (prop, name_cnt, c_arg_p, c_arg_cnt); 156425bb815Sopenharmony_ci 157425bb815Sopenharmony_ci for (jerry_length_t i = 0; i < name_cnt; i++) 158425bb815Sopenharmony_ci { 159425bb815Sopenharmony_ci jerry_release_value (prop[i]); 160425bb815Sopenharmony_ci } 161425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 162425bb815Sopenharmony_ci jerry_vla_free ((char*)prop); 163425bb815Sopenharmony_ci#endif 164425bb815Sopenharmony_ci return ret; 165425bb815Sopenharmony_ci} /* jerryx_arg_transform_object_properties */ 166425bb815Sopenharmony_ci 167425bb815Sopenharmony_ci/** 168425bb815Sopenharmony_ci * Validate the items in the JS array and assign them to the native arguments. 169425bb815Sopenharmony_ci * 170425bb815Sopenharmony_ci * @return jerry undefined: all validators passed, 171425bb815Sopenharmony_ci * jerry error: a validator failed. 172425bb815Sopenharmony_ci */ 173425bb815Sopenharmony_cijerry_value_t 174425bb815Sopenharmony_cijerryx_arg_transform_array (const jerry_value_t array_val, /**< points to the JS array */ 175425bb815Sopenharmony_ci const jerryx_arg_t *c_arg_p, /**< points to the array of validation/transformation steps */ 176425bb815Sopenharmony_ci jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 177425bb815Sopenharmony_ci{ 178425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 179425bb815Sopenharmony_ci jerry_value_t* arr; 180425bb815Sopenharmony_ci jerry_value_t arr_i; 181425bb815Sopenharmony_ci#endif 182425bb815Sopenharmony_ci if (!jerry_value_is_array (array_val)) 183425bb815Sopenharmony_ci { 184425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "Not an array."); 185425bb815Sopenharmony_ci } 186425bb815Sopenharmony_ci 187425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 188425bb815Sopenharmony_ci arr = (jerry_value_t*) jerry_vla_malloc (sizeof(jerry_value_t) * c_arg_cnt); 189425bb815Sopenharmony_ci if (!arr) 190425bb815Sopenharmony_ci { 191425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "malloc arr fail."); 192425bb815Sopenharmony_ci } 193425bb815Sopenharmony_ci#else 194425bb815Sopenharmony_ci JERRY_VLA (jerry_value_t, arr, c_arg_cnt); 195425bb815Sopenharmony_ci#endif 196425bb815Sopenharmony_ci for (jerry_length_t i = 0; i < c_arg_cnt; i++) 197425bb815Sopenharmony_ci { 198425bb815Sopenharmony_ci arr[i] = jerry_get_property_by_index (array_val, i); 199425bb815Sopenharmony_ci 200425bb815Sopenharmony_ci if (jerry_value_is_error (arr[i])) 201425bb815Sopenharmony_ci { 202425bb815Sopenharmony_ci for (jerry_length_t j = 0; j < i; j++) 203425bb815Sopenharmony_ci { 204425bb815Sopenharmony_ci jerry_release_value (arr[j]); 205425bb815Sopenharmony_ci } 206425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 207425bb815Sopenharmony_ci arr_i = arr[i]; 208425bb815Sopenharmony_ci jerry_vla_free ((char*)arr); 209425bb815Sopenharmony_ci return arr_i; 210425bb815Sopenharmony_ci#else 211425bb815Sopenharmony_ci return arr[i]; 212425bb815Sopenharmony_ci#endif 213425bb815Sopenharmony_ci } 214425bb815Sopenharmony_ci } 215425bb815Sopenharmony_ci 216425bb815Sopenharmony_ci const jerry_value_t ret = jerryx_arg_transform_args (arr, c_arg_cnt, c_arg_p, c_arg_cnt); 217425bb815Sopenharmony_ci 218425bb815Sopenharmony_ci for (jerry_length_t i = 0; i < c_arg_cnt; i++) 219425bb815Sopenharmony_ci { 220425bb815Sopenharmony_ci jerry_release_value (arr[i]); 221425bb815Sopenharmony_ci } 222425bb815Sopenharmony_ci#if defined(JERRY_FOR_IAR_CONFIG) 223425bb815Sopenharmony_ci jerry_vla_free ((char*)arr); 224425bb815Sopenharmony_ci#endif 225425bb815Sopenharmony_ci return ret; 226425bb815Sopenharmony_ci} /* jerryx_arg_transform_array */ 227