• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
26 JERRYX_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  */
37 jerry_value_t
jerryx_arg_transform_args(const jerry_value_t * js_arg_p,const jerry_length_t js_arg_cnt,const jerryx_arg_t * c_arg_p,jerry_length_t c_arg_cnt)38 jerryx_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  */
70 jerry_value_t
jerryx_arg_transform_this_and_args(const jerry_value_t this_val,const jerry_value_t * js_arg_p,const jerry_length_t js_arg_cnt,const jerryx_arg_t * c_arg_p,jerry_length_t c_arg_cnt)71 jerryx_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  */
108 jerry_value_t
jerryx_arg_transform_object_properties(const jerry_value_t obj_val,const jerry_char_t ** name_p,const jerry_length_t name_cnt,const jerryx_arg_t * c_arg_p,jerry_length_t c_arg_cnt)109 jerryx_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  */
173 jerry_value_t
jerryx_arg_transform_array(const jerry_value_t array_val,const jerryx_arg_t * c_arg_p,jerry_length_t c_arg_cnt)174 jerryx_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