1/* Copyright JS Foundation and other contributors, http://js.foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "arg-internal.h" 17#include "jerryscript-ext/arg.h" 18#include "jerryscript.h" 19#if defined(JERRY_FOR_IAR_CONFIG) 20#include "jerryscript-core.h" 21#endif 22 23#define JERRYX_STATIC_ASSERT(x, msg) \ 24 enum { static_assertion_failed_ ## msg = 1 / (!!(x)) } 25 26JERRYX_STATIC_ASSERT (sizeof (jerryx_arg_int_option_t) <= sizeof (((jerryx_arg_t *) 0)->extra_info), 27 jerryx_arg_number_options_t_must_fit_into_extra_info); 28 29#undef JERRYX_STATIC_ASSERT 30 31/** 32 * Validate the JS arguments and assign them to the native arguments. 33 * 34 * @return jerry undefined: all validators passed, 35 * jerry error: a validator failed. 36 */ 37jerry_value_t 38jerryx_arg_transform_args (const jerry_value_t *js_arg_p, /**< points to the array with JS arguments */ 39 const jerry_length_t js_arg_cnt, /**< the count of the `js_arg_p` array */ 40 const jerryx_arg_t *c_arg_p, /**< points to the array of validation/transformation steps */ 41 jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 42{ 43 jerry_value_t ret = jerry_create_undefined (); 44 45 jerryx_arg_js_iterator_t iterator = 46 { 47 .js_arg_p = js_arg_p, 48 .js_arg_cnt = js_arg_cnt, 49 .js_arg_idx = 0 50 }; 51 52 for (; c_arg_cnt != 0 && !jerry_value_is_error (ret); c_arg_cnt--, c_arg_p++) 53 { 54 ret = c_arg_p->func (&iterator, c_arg_p); 55 } 56 57 return ret; 58} /* jerryx_arg_transform_args */ 59 60/** 61 * Validate the this value and the JS arguments, 62 * and assign them to the native arguments. 63 * This function is useful to perform input validation inside external 64 * function handlers (see jerry_external_handler_t). 65 * @note this_val is processed as the first value, before the array of arguments. 66 * 67 * @return jerry undefined: all validators passed, 68 * jerry error: a validator failed. 69 */ 70jerry_value_t 71jerryx_arg_transform_this_and_args (const jerry_value_t this_val, /**< the this_val for the external function */ 72 const jerry_value_t *js_arg_p, /**< points to the array with JS arguments */ 73 const jerry_length_t js_arg_cnt, /**< the count of the `js_arg_p` array */ 74 const jerryx_arg_t *c_arg_p, /**< points to the array of transformation steps */ 75 jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 76{ 77 if (c_arg_cnt == 0) 78 { 79 return jerry_create_undefined (); 80 } 81 82 jerryx_arg_js_iterator_t iterator = 83 { 84 .js_arg_p = &this_val, 85 .js_arg_cnt = 1, 86 .js_arg_idx = 0 87 }; 88 89 jerry_value_t ret = c_arg_p->func (&iterator, c_arg_p); 90 91 if (jerry_value_is_error (ret)) 92 { 93 jerry_release_value (ret); 94 95 return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "'this' validation failed."); 96 } 97 98 return jerryx_arg_transform_args (js_arg_p, js_arg_cnt, c_arg_p + 1, c_arg_cnt - 1); 99} /* jerryx_arg_transform_this_and_args */ 100 101/** 102 * Validate the `obj_val`'s properties, 103 * and assign them to the native arguments. 104 * 105 * @return jerry undefined: all validators passed, 106 * jerry error: a validator failed. 107 */ 108jerry_value_t 109jerryx_arg_transform_object_properties (const jerry_value_t obj_val,/**< the JS object */ 110 const jerry_char_t **name_p, /**< property name list of the JS object */ 111 const jerry_length_t name_cnt, /**< count of the name list */ 112 const jerryx_arg_t *c_arg_p, /**< points to the array of transformation steps */ 113 jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 114{ 115#if defined(JERRY_FOR_IAR_CONFIG) 116 jerry_value_t* prop; 117 jerry_value_t prop_i; 118#endif 119 if (!jerry_value_is_object (obj_val)) 120 { 121 return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "Not an object."); 122 } 123 124#if defined(JERRY_FOR_IAR_CONFIG) 125 prop = (jerry_value_t*) jerry_vla_malloc (sizeof(jerry_value_t) * name_cnt); 126 if (!prop) 127 { 128 return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "malloc prop fail."); 129 } 130#else 131 JERRY_VLA (jerry_value_t, prop, name_cnt); 132#endif 133 for (jerry_length_t i = 0; i < name_cnt; i++, name_p++) 134 { 135 const jerry_value_t name_str = jerry_create_string (*name_p); 136 prop[i] = jerry_get_property (obj_val, name_str); 137 jerry_release_value (name_str); 138 139 if (jerry_value_is_error (prop[i])) 140 { 141 for (jerry_length_t j = 0; j < i; j++) 142 { 143 jerry_release_value (prop[j]); 144 } 145#if defined(JERRY_FOR_IAR_CONFIG) 146 prop_i = prop[i]; 147 jerry_vla_free ((char*)prop); 148 return prop_i; 149#else 150 return prop[i]; 151#endif 152 } 153 } 154 155 const jerry_value_t ret = jerryx_arg_transform_args (prop, name_cnt, c_arg_p, c_arg_cnt); 156 157 for (jerry_length_t i = 0; i < name_cnt; i++) 158 { 159 jerry_release_value (prop[i]); 160 } 161#if defined(JERRY_FOR_IAR_CONFIG) 162 jerry_vla_free ((char*)prop); 163#endif 164 return ret; 165} /* jerryx_arg_transform_object_properties */ 166 167/** 168 * Validate the items in the JS array and assign them to the native arguments. 169 * 170 * @return jerry undefined: all validators passed, 171 * jerry error: a validator failed. 172 */ 173jerry_value_t 174jerryx_arg_transform_array (const jerry_value_t array_val, /**< points to the JS array */ 175 const jerryx_arg_t *c_arg_p, /**< points to the array of validation/transformation steps */ 176 jerry_length_t c_arg_cnt) /**< the count of the `c_arg_p` array */ 177{ 178#if defined(JERRY_FOR_IAR_CONFIG) 179 jerry_value_t* arr; 180 jerry_value_t arr_i; 181#endif 182 if (!jerry_value_is_array (array_val)) 183 { 184 return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "Not an array."); 185 } 186 187#if defined(JERRY_FOR_IAR_CONFIG) 188 arr = (jerry_value_t*) jerry_vla_malloc (sizeof(jerry_value_t) * c_arg_cnt); 189 if (!arr) 190 { 191 return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "malloc arr fail."); 192 } 193#else 194 JERRY_VLA (jerry_value_t, arr, c_arg_cnt); 195#endif 196 for (jerry_length_t i = 0; i < c_arg_cnt; i++) 197 { 198 arr[i] = jerry_get_property_by_index (array_val, i); 199 200 if (jerry_value_is_error (arr[i])) 201 { 202 for (jerry_length_t j = 0; j < i; j++) 203 { 204 jerry_release_value (arr[j]); 205 } 206#if defined(JERRY_FOR_IAR_CONFIG) 207 arr_i = arr[i]; 208 jerry_vla_free ((char*)arr); 209 return arr_i; 210#else 211 return arr[i]; 212#endif 213 } 214 } 215 216 const jerry_value_t ret = jerryx_arg_transform_args (arr, c_arg_cnt, c_arg_p, c_arg_cnt); 217 218 for (jerry_length_t i = 0; i < c_arg_cnt; i++) 219 { 220 jerry_release_value (arr[i]); 221 } 222#if defined(JERRY_FOR_IAR_CONFIG) 223 jerry_vla_free ((char*)arr); 224#endif 225 return ret; 226} /* jerryx_arg_transform_array */ 227