• 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 /**
17  * Unit test for jerry-ext/handler property registration
18  */
19 
20 #include "jerryscript.h"
21 #include "jerryscript-ext/handler.h"
22 #include "test-common.h"
23 
24 #include <string.h>
25 
26 static jerry_value_t
method_hello(const jerry_value_t jfunc,const jerry_value_t jthis,const jerry_value_t jargv[],const jerry_length_t jargc)27 method_hello (const jerry_value_t jfunc,  /**< function object */
28               const jerry_value_t jthis,  /**< function this */
29               const jerry_value_t jargv[], /**< arguments */
30               const jerry_length_t jargc) /**< number of arguments */
31 {
32   (void) jfunc;
33   (void) jthis;
34   (void) jargv;
35   return jerry_create_number (jargc);
36 } /* method_hello */
37 
38 /**
39  * Helper method to create a non-configurable property on an object
40  */
41 static void
freeze_property(jerry_value_t target_obj,const char * target_prop)42 freeze_property (jerry_value_t target_obj, /**< target object */
43                  const char *target_prop) /**< target property name */
44 {
45   // "freeze" property
46   jerry_property_descriptor_t prop_desc;
47   jerry_init_property_descriptor_fields (&prop_desc);
48   prop_desc.is_configurable_defined = true;
49   prop_desc.is_configurable = false;
50 
51   jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) target_prop);
52   jerry_value_t return_value = jerry_define_own_property (target_obj, prop_name, &prop_desc);
53   TEST_ASSERT (jerry_value_is_boolean (return_value));
54   jerry_release_value (return_value);
55   jerry_release_value (prop_name);
56 
57   jerry_free_property_descriptor_fields (&prop_desc);
58 } /* freeze_property */
59 
60 /**
61  * Test registration of various property values.
62  */
63 static void
test_simple_registration(void)64 test_simple_registration (void)
65 {
66   jerry_init (JERRY_INIT_EMPTY);
67 
68   jerry_value_t target_object = jerry_create_object ();
69 
70   // Test simple registration
71   jerryx_property_entry methods[] =
72   {
73     JERRYX_PROPERTY_FUNCTION ("hello", method_hello),
74     JERRYX_PROPERTY_NUMBER ("my_number", 42.5),
75     JERRYX_PROPERTY_STRING ("my_str", "super_str"),
76     JERRYX_PROPERTY_STRING_SZ ("my_str_sz", "super_str", 6),
77     JERRYX_PROPERTY_BOOLEAN ("my_bool", true),
78     JERRYX_PROPERTY_BOOLEAN ("my_bool_false", false),
79     JERRYX_PROPERTY_UNDEFINED ("my_non_value"),
80     JERRYX_PROPERTY_LIST_END (),
81   };
82 
83   jerryx_register_result register_result = jerryx_set_properties (target_object, methods);
84 
85   TEST_ASSERT (register_result.registered == 7);
86   TEST_ASSERT (jerry_value_is_undefined (register_result.result));
87 
88   jerryx_release_property_entry (methods, register_result);
89   jerry_release_value (register_result.result);
90 
91   jerry_value_t global_obj = jerry_get_global_object ();
92   jerryx_set_property_str (global_obj, "test", target_object);
93   jerry_release_value (target_object);
94   jerry_release_value (global_obj);
95 
96   {
97     const char *test_A = "test.my_number";
98     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
99     TEST_ASSERT (jerry_value_is_number (result));
100     TEST_ASSERT (jerry_get_number_value (result) == 42.5);
101     jerry_release_value (result);
102   }
103 
104   {
105     const char *test_A = "test.my_str_sz === 'super_'";
106     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
107     TEST_ASSERT (jerry_value_is_boolean (result));
108     TEST_ASSERT (jerry_get_boolean_value (result) == true);
109     jerry_release_value (result);
110   }
111 
112   {
113     const char *test_A = "test.my_str === 'super_str'";
114     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
115     TEST_ASSERT (jerry_value_is_boolean (result));
116     TEST_ASSERT (jerry_get_boolean_value (result) == true);
117     jerry_release_value (result);
118   }
119 
120   {
121     const char *test_A = "test.my_bool";
122     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
123     TEST_ASSERT (jerry_value_is_boolean (result));
124     TEST_ASSERT (jerry_get_boolean_value (result) == true);
125     jerry_release_value (result);
126   }
127 
128   {
129     const char *test_A = "test.my_bool_false";
130     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
131     TEST_ASSERT (jerry_value_is_boolean (result));
132     TEST_ASSERT (jerry_get_boolean_value (result) == false);
133     jerry_release_value (result);
134   }
135 
136   {
137     const char *test_A = "test.my_non_value";
138     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
139     TEST_ASSERT (jerry_value_is_undefined (result));
140     jerry_release_value (result);
141   }
142 
143   {
144     const char *test_A = "test.hello(33, 42, 2);";
145     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
146     TEST_ASSERT (jerry_value_is_number (result));
147     TEST_ASSERT ((uint32_t) jerry_get_number_value (result) == 3u);
148     jerry_release_value (result);
149   }
150 
151   {
152     const char *test_A = "test.hello();";
153     jerry_value_t result = jerry_eval ((const jerry_char_t *) test_A, strlen (test_A), 0);
154     TEST_ASSERT (jerry_value_is_number (result));
155     TEST_ASSERT ((uint32_t) jerry_get_number_value (result) == 0u);
156     jerry_release_value (result);
157   }
158 
159   jerry_cleanup ();
160 } /* test_simple_registration */
161 
162 /**
163  * Test registration error.
164  *
165  * Trying to register a property which is already a non-configurable property
166  * should result in an error.
167  */
168 static void
test_error_setvalue(void)169 test_error_setvalue (void)
170 {
171   jerry_init (JERRY_INIT_EMPTY);
172 
173   const char *target_prop = "test_err";
174   jerry_value_t global_obj = jerry_get_global_object ();
175   freeze_property (global_obj, target_prop);
176 
177   jerry_value_t new_object = jerry_create_object ();
178   jerry_value_t set_result = jerryx_set_property_str (global_obj, target_prop, new_object);
179   TEST_ASSERT (jerry_value_is_error (set_result));
180 
181   jerry_release_value (set_result);
182   jerry_release_value (new_object);
183   jerry_release_value (global_obj);
184 
185   jerry_cleanup ();
186 } /* test_error_setvalue */
187 
188 /**
189  * Test registration error with jerryx_set_properties.
190  *
191  * Trying to register a property which is already a non-configurable property
192  * should result in an error.
193  */
194 static void
test_error_single_function(void)195 test_error_single_function (void)
196 {
197   jerry_init (JERRY_INIT_EMPTY);
198 
199   const char *target_prop = "test_err";
200   jerry_value_t target_object = jerry_create_object ();
201   freeze_property (target_object, target_prop);
202 
203   jerryx_property_entry methods[] =
204   {
205     JERRYX_PROPERTY_FUNCTION (target_prop, method_hello), // This registration should fail
206     JERRYX_PROPERTY_LIST_END (),
207   };
208 
209   jerryx_register_result register_result = jerryx_set_properties (target_object, methods);
210 
211   TEST_ASSERT (register_result.registered == 0);
212   TEST_ASSERT (jerry_value_is_error (register_result.result));
213   jerryx_release_property_entry (methods, register_result);
214   jerry_release_value (register_result.result);
215 
216   jerry_release_value (target_object);
217 
218   jerry_cleanup ();
219 } /* test_error_single_function */
220 
221 /**
222  * Test to see if jerryx_set_properties exits at the first error.
223  */
224 static void
test_error_multiple_functions(void)225 test_error_multiple_functions (void)
226 {
227   jerry_init (JERRY_INIT_EMPTY);
228 
229   const char *prop_ok = "prop_ok";
230   const char *prop_err = "prop_err";
231   const char *prop_not = "prop_not";
232   jerry_value_t target_object = jerry_create_object ();
233   freeze_property (target_object, prop_err);
234 
235   jerryx_property_entry methods[] =
236   {
237     JERRYX_PROPERTY_FUNCTION (prop_ok, method_hello), // This registration is ok
238     JERRYX_PROPERTY_FUNCTION (prop_err, method_hello), // This registration should fail
239     JERRYX_PROPERTY_FUNCTION (prop_not, method_hello), // This registration is not done
240     JERRYX_PROPERTY_LIST_END (),
241   };
242 
243   jerryx_register_result register_result = jerryx_set_properties (target_object, methods);
244 
245   TEST_ASSERT (register_result.registered == 1);
246   TEST_ASSERT (jerry_value_is_error (register_result.result));
247 
248   jerryx_release_property_entry (methods, register_result);
249   jerry_release_value (register_result.result);
250 
251   {
252     // Test if property "prop_ok" is correctly registered.
253     jerry_value_t prop_ok_val = jerry_create_string ((const jerry_char_t *) prop_ok);
254     jerry_value_t prop_ok_exists = jerry_has_own_property (target_object, prop_ok_val);
255     TEST_ASSERT (jerry_get_boolean_value (prop_ok_exists) == true);
256     jerry_release_value (prop_ok_exists);
257 
258     // Try calling the method
259     jerry_value_t prop_ok_func = jerry_get_property (target_object, prop_ok_val);
260     TEST_ASSERT (jerry_value_is_function (prop_ok_func) == true);
261     jerry_value_t args[2] =
262     {
263       jerry_create_number (22),
264       jerry_create_number (-3),
265     };
266     jerry_size_t args_cnt = sizeof (args) / sizeof (jerry_value_t);
267     jerry_value_t func_result = jerry_call_function (prop_ok_func,
268                                                      jerry_create_undefined (),
269                                                      args,
270                                                      args_cnt);
271     TEST_ASSERT (jerry_value_is_number (func_result) == true);
272     TEST_ASSERT ((uint32_t) jerry_get_number_value (func_result) == 2u);
273     jerry_release_value (func_result);
274     for (jerry_size_t idx = 0; idx < args_cnt; idx++)
275     {
276       jerry_release_value (args[idx]);
277     }
278     jerry_release_value (prop_ok_func);
279     jerry_release_value (prop_ok_val);
280   }
281 
282   {
283     // The "prop_err" should exist - as it was "freezed" - but it should not be a function
284     jerry_value_t prop_err_val = jerry_create_string ((const jerry_char_t *) prop_err);
285     jerry_value_t prop_err_exists = jerry_has_own_property (target_object, prop_err_val);
286     TEST_ASSERT (jerry_get_boolean_value (prop_err_exists) == true);
287     jerry_release_value (prop_err_exists);
288 
289     jerry_value_t prop_err_func = jerry_value_is_function (prop_err_val);
290     TEST_ASSERT (jerry_value_is_function (prop_err_func) == false);
291     jerry_release_value (prop_err_val);
292   }
293 
294   { // The "prop_not" is not available on the target object
295     jerry_value_t prop_not_val = jerry_create_string ((const jerry_char_t *) prop_not);
296     jerry_value_t prop_not_exists = jerry_has_own_property (target_object, prop_not_val);
297     TEST_ASSERT (jerry_get_boolean_value (prop_not_exists) == false);
298     jerry_release_value (prop_not_exists);
299     jerry_release_value (prop_not_val);
300   }
301 
302   jerry_release_value (target_object);
303 
304   jerry_cleanup ();
305 } /* test_error_multiple_functions */
306 
307 int
main(void)308 main (void)
309 {
310   test_simple_registration ();
311   test_error_setvalue ();
312   test_error_single_function ();
313   test_error_multiple_functions ();
314   return 0;
315 } /* main */
316