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 "config.h"
17 #include "jerryscript.h"
18
19 #include "test-common.h"
20
21 const jerry_char_t test_source[] = TEST_STRING_LITERAL (
22 "function assert (arg) { "
23 " if (!arg) { "
24 " throw Error('Assert failed');"
25 " } "
26 "} "
27 "this.t = 1; "
28 "function f () { "
29 "return this.t; "
30 "} "
31 "this.foo = f; "
32 "this.bar = function (a) { "
33 "return a + t; "
34 "}; "
35 "function A () { "
36 "this.t = 12; "
37 "} "
38 "this.A = A; "
39 "this.a = new A (); "
40 "function call_external () { "
41 " return this.external ('1', true); "
42 "} "
43 "function call_throw_test() { "
44 " var catched = false; "
45 " try { "
46 " this.throw_test(); "
47 " } catch (e) { "
48 " catched = true; "
49 " assert(e.name == 'TypeError'); "
50 " assert(e.message == 'error'); "
51 " } "
52 " assert(catched); "
53 "} "
54 "function throw_reference_error() { "
55 " throw new ReferenceError ();"
56 "} "
57 "p = {'alpha':32, 'bravo':false, 'charlie':{}, 'delta':123.45, 'echo':'foobar'};"
58 "np = {}; Object.defineProperty (np, 'foxtrot', { "
59 "get: function() { throw 'error'; }, enumerable: true }) "
60 );
61
62 bool test_api_is_free_callback_was_called = false;
63
64 static jerry_value_t
handler(const jerry_value_t func_obj_val,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_cnt)65 handler (const jerry_value_t func_obj_val, /**< function object */
66 const jerry_value_t this_val, /**< this value */
67 const jerry_value_t args_p[], /**< arguments list */
68 const jerry_length_t args_cnt) /**< arguments length */
69 {
70 char buffer[32];
71 jerry_size_t sz;
72
73 printf ("ok %u %u %p %u\n",
74 (unsigned int) func_obj_val, (unsigned int) this_val, (void *) args_p, (unsigned int) args_cnt);
75
76 TEST_ASSERT (args_cnt == 2);
77
78 TEST_ASSERT (jerry_value_is_string (args_p[0]));
79 sz = jerry_get_string_size (args_p[0]);
80 TEST_ASSERT (sz == 1);
81 sz = jerry_string_to_char_buffer (args_p[0],
82 (jerry_char_t *) buffer,
83 sz);
84 TEST_ASSERT (sz == 1);
85 TEST_ASSERT (!strncmp (buffer, "1", (size_t) sz));
86
87 TEST_ASSERT (jerry_value_is_boolean (args_p[1]));
88
89 return jerry_create_string ((jerry_char_t *) "string from handler");
90 } /* handler */
91
92 static jerry_value_t
handler_throw_test(const jerry_value_t func_obj_val,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_cnt)93 handler_throw_test (const jerry_value_t func_obj_val, /**< function object */
94 const jerry_value_t this_val, /**< this value */
95 const jerry_value_t args_p[], /**< arguments list */
96 const jerry_length_t args_cnt) /**< arguments length */
97 {
98 printf ("ok %u %u %p %u\n",
99 (unsigned int) func_obj_val, (unsigned int) this_val, (void *) args_p, (unsigned int) args_cnt);
100
101 return jerry_create_error (JERRY_ERROR_TYPE, (jerry_char_t *) "error");
102 } /* handler_throw_test */
103
104 static void
handler_construct_1_freecb(void * native_p)105 handler_construct_1_freecb (void *native_p)
106 {
107 TEST_ASSERT ((uintptr_t) native_p == (uintptr_t) 0x0000000000000000ull);
108 printf ("ok object free callback\n");
109
110 test_api_is_free_callback_was_called = true;
111 } /* handler_construct_1_freecb */
112
113 static void
handler_construct_2_freecb(void * native_p)114 handler_construct_2_freecb (void *native_p)
115 {
116 TEST_ASSERT ((uintptr_t) native_p == (uintptr_t) 0x0012345678abcdefull);
117 printf ("ok object free callback\n");
118
119 test_api_is_free_callback_was_called = true;
120 } /* handler_construct_2_freecb */
121
122 /**
123 * The name of the jerry_object_native_info_t struct.
124 */
125 #define JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE(c_type) _jerry_object_native_info_##c_type
126
127 /**
128 * Define a native pointer's type based on the C type and free callback.
129 */
130 #define JERRY_DEFINE_NATIVE_HANDLE_INFO(c_type, native_free_cb) \
131 static const jerry_object_native_info_t JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (c_type) = \
132 { \
133 .free_cb = (jerry_object_native_free_callback_t) native_free_cb \
134 }
135
136 JERRY_DEFINE_NATIVE_HANDLE_INFO (bind1, handler_construct_1_freecb);
137 JERRY_DEFINE_NATIVE_HANDLE_INFO (bind2, handler_construct_2_freecb);
138 JERRY_DEFINE_NATIVE_HANDLE_INFO (bind3, NULL);
139
140 static jerry_value_t
handler_construct(const jerry_value_t func_obj_val,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_cnt)141 handler_construct (const jerry_value_t func_obj_val, /**< function object */
142 const jerry_value_t this_val, /**< this value */
143 const jerry_value_t args_p[], /**< arguments list */
144 const jerry_length_t args_cnt) /**< arguments length */
145 {
146 printf ("ok construct %u %u %p %u\n",
147 (unsigned int) func_obj_val, (unsigned int) this_val, (void *) args_p, (unsigned int) args_cnt);
148
149 TEST_ASSERT (jerry_value_is_object (this_val));
150
151 TEST_ASSERT (args_cnt == 1);
152 TEST_ASSERT (jerry_value_is_boolean (args_p[0]));
153 TEST_ASSERT (jerry_get_boolean_value (args_p[0]) == true);
154
155 jerry_value_t field_name = jerry_create_string ((jerry_char_t *) "value_field");
156 jerry_value_t res = jerry_set_property (this_val, field_name, args_p[0]);
157 TEST_ASSERT (!jerry_value_is_error (res));
158 TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res));
159 jerry_release_value (res);
160 jerry_release_value (field_name);
161
162 /* Set a native pointer. */
163 jerry_set_object_native_pointer (this_val,
164 (void *) 0x0000000000000000ull,
165 &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind1));
166
167 /* Check that the native pointer was set. */
168 void *ptr = NULL;
169 bool is_ok = jerry_get_object_native_pointer (this_val, &ptr, &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind1));
170 TEST_ASSERT (is_ok
171 && (uintptr_t) ptr == (uintptr_t) 0x0000000000000000ull);
172
173 /* Set a second native pointer. */
174 jerry_set_object_native_pointer (this_val,
175 (void *) 0x0012345678abcdefull,
176 &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind2));
177
178 /* Check that a second native pointer was set. */
179 is_ok = jerry_get_object_native_pointer (this_val, &ptr, &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind2));
180 TEST_ASSERT (is_ok
181 && (uintptr_t) ptr == (uintptr_t) 0x0012345678abcdefull);
182
183 /* Check that the first native pointer is still set. */
184 is_ok = jerry_get_object_native_pointer (this_val, &ptr, &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind1));
185 TEST_ASSERT (is_ok
186 && (uintptr_t) ptr == (uintptr_t) 0x0000000000000000ull);
187 return jerry_create_boolean (true);
188 } /* handler_construct */
189
190 /**
191 * Extended Magic Strings
192 */
193 #define JERRY_MAGIC_STRING_ITEMS \
194 JERRY_MAGIC_STRING_DEF (GLOBAL, global) \
195 JERRY_MAGIC_STRING_DEF (GREEK_ZERO_SIGN, \xed\xa0\x80\xed\xb6\x8a) \
196 JERRY_MAGIC_STRING_DEF (CONSOLE, console)
197
198 #define JERRY_MAGIC_STRING_DEF(NAME, STRING) \
199 static const char jerry_magic_string_ex_ ## NAME[] = # STRING;
200
201 JERRY_MAGIC_STRING_ITEMS
202
203 #undef JERRY_MAGIC_STRING_DEF
204
205 const jerry_length_t magic_string_lengths[] =
206 {
207 #define JERRY_MAGIC_STRING_DEF(NAME, STRING) \
208 (jerry_length_t) (sizeof (jerry_magic_string_ex_ ## NAME) - 1u),
209
210 JERRY_MAGIC_STRING_ITEMS
211
212 #undef JERRY_MAGIC_STRING_DEF
213 };
214
215 const jerry_char_t *magic_string_items[] =
216 {
217 #define JERRY_MAGIC_STRING_DEF(NAME, STRING) \
218 (const jerry_char_t *) jerry_magic_string_ex_ ## NAME,
219
220 JERRY_MAGIC_STRING_ITEMS
221
222 #undef JERRY_MAGIC_STRING_DEF
223 };
224
225 static bool
foreach(const jerry_value_t name,const jerry_value_t value,void * user_data)226 foreach (const jerry_value_t name, /**< field name */
227 const jerry_value_t value, /**< field value */
228 void *user_data) /**< user data */
229 {
230 char str_buf_p[128];
231 jerry_size_t sz = jerry_string_to_char_buffer (name, (jerry_char_t *) str_buf_p, 128);
232 str_buf_p[sz] = '\0';
233
234 TEST_ASSERT (!strncmp ((const char *) user_data, "user_data", 9));
235 TEST_ASSERT (sz > 0);
236
237 if (!strncmp (str_buf_p, "alpha", (size_t) sz))
238 {
239 TEST_ASSERT (jerry_value_is_number (value));
240 TEST_ASSERT (jerry_get_number_value (value) == 32.0);
241 return true;
242 }
243 else if (!strncmp (str_buf_p, "bravo", (size_t) sz))
244 {
245 TEST_ASSERT (jerry_value_is_boolean (value));
246 TEST_ASSERT (jerry_get_boolean_value (value) == false);
247 return true;
248 }
249 else if (!strncmp (str_buf_p, "charlie", (size_t) sz))
250 {
251 TEST_ASSERT (jerry_value_is_object (value));
252 return true;
253 }
254 else if (!strncmp (str_buf_p, "delta", (size_t) sz))
255 {
256 TEST_ASSERT (jerry_value_is_number (value));
257 TEST_ASSERT (jerry_get_number_value (value) == 123.45);
258 return true;
259 }
260 else if (!strncmp (str_buf_p, "echo", (size_t) sz))
261 {
262 TEST_ASSERT (jerry_value_is_string (value));
263 jerry_size_t echo_sz = jerry_string_to_char_buffer (value,
264 (jerry_char_t *) str_buf_p,
265 128);
266 str_buf_p[echo_sz] = '\0';
267 TEST_ASSERT (!strncmp (str_buf_p, "foobar", (size_t) echo_sz));
268 return true;
269 }
270
271 TEST_ASSERT (false);
272 return false;
273 } /* foreach */
274
275 static bool
foreach_exception(const jerry_value_t name,const jerry_value_t value,void * user_data)276 foreach_exception (const jerry_value_t name, /**< field name */
277 const jerry_value_t value, /**< field value */
278 void *user_data) /**< user data */
279 {
280 JERRY_UNUSED (value);
281 JERRY_UNUSED (user_data);
282 char str_buf_p[128];
283 jerry_size_t sz = jerry_string_to_char_buffer (name, (jerry_char_t *) str_buf_p, 128);
284 str_buf_p[sz] = '\0';
285
286 if (!strncmp (str_buf_p, "foxtrot", (size_t) sz))
287 {
288 TEST_ASSERT (false);
289 }
290
291 return true;
292 } /* foreach_exception */
293
294 static bool
foreach_subset(const jerry_value_t name,const jerry_value_t value,void * user_data)295 foreach_subset (const jerry_value_t name, /**< field name */
296 const jerry_value_t value, /**< field value */
297 void *user_data) /**< user data */
298 {
299 JERRY_UNUSED (name);
300 JERRY_UNUSED (value);
301 int *count_p = (int *) (user_data);
302
303 if (*count_p == 3)
304 {
305 return false;
306 }
307 (*count_p)++;
308 return true;
309 } /* foreach_subset */
310
311 static jerry_value_t
get_property(const jerry_value_t obj_val,const char * str_p)312 get_property (const jerry_value_t obj_val, /**< object value */
313 const char *str_p) /**< property name */
314 {
315 jerry_value_t prop_name_val = jerry_create_string ((const jerry_char_t *) str_p);
316 jerry_value_t ret_val = jerry_get_property (obj_val, prop_name_val);
317 jerry_release_value (prop_name_val);
318 return ret_val;
319 } /* get_property */
320
321 static jerry_value_t
set_property(const jerry_value_t obj_val,const char * str_p,const jerry_value_t val)322 set_property (const jerry_value_t obj_val, /**< object value */
323 const char *str_p, /**< property name */
324 const jerry_value_t val) /**< value to set */
325 {
326 jerry_value_t prop_name_val = jerry_create_string ((const jerry_char_t *) str_p);
327 jerry_value_t ret_val = jerry_set_property (obj_val, prop_name_val, val);
328 jerry_release_value (prop_name_val);
329 return ret_val;
330 } /* set_property */
331
332 static bool
test_run_simple(const char * script_p)333 test_run_simple (const char *script_p) /**< source code to run */
334 {
335 size_t script_size = strlen (script_p);
336
337 return jerry_run_simple ((const jerry_char_t *) script_p, script_size, JERRY_INIT_EMPTY);
338 } /* test_run_simple */
339
340 int
main(void)341 main (void)
342 {
343 TEST_INIT ();
344
345 bool is_ok;
346 jerry_size_t sz, cesu8_sz;
347 jerry_length_t cesu8_length;
348 jerry_value_t val_t, val_foo, val_bar, val_A, val_A_prototype, val_a, val_a_foo, val_value_field, val_p, val_np;
349 jerry_value_t val_call_external;
350 jerry_value_t global_obj_val, obj_val;
351 jerry_value_t external_func_val, external_construct_val;
352 jerry_value_t throw_test_handler_val;
353 jerry_value_t parsed_code_val, proto_val, prim_val;
354 jerry_value_t res, args[2];
355 double number_val;
356 char buffer[32];
357
358 is_ok = test_run_simple ("throw 'Hello World';");
359 TEST_ASSERT (!is_ok);
360
361 jerry_init (JERRY_INIT_EMPTY);
362
363 parsed_code_val = jerry_parse (NULL,
364 0,
365 test_source,
366 sizeof (test_source) - 1,
367 JERRY_PARSE_NO_OPTS);
368 TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
369
370 res = jerry_run (parsed_code_val);
371 TEST_ASSERT (!jerry_value_is_error (res));
372 jerry_release_value (res);
373 jerry_release_value (parsed_code_val);
374
375 global_obj_val = jerry_get_global_object ();
376
377 /* Get global.boo (non-existing field) */
378 val_t = get_property (global_obj_val, "boo");
379 TEST_ASSERT (!jerry_value_is_error (val_t));
380 TEST_ASSERT (jerry_value_is_undefined (val_t));
381
382 /* Get global.t */
383 val_t = get_property (global_obj_val, "t");
384 TEST_ASSERT (!jerry_value_is_error (val_t));
385 TEST_ASSERT (jerry_value_is_number (val_t)
386 && jerry_get_number_value (val_t) == 1.0);
387 jerry_release_value (val_t);
388
389 /* Get global.foo */
390 val_foo = get_property (global_obj_val, "foo");
391 TEST_ASSERT (!jerry_value_is_error (val_foo));
392 TEST_ASSERT (jerry_value_is_object (val_foo));
393
394 /* Call foo (4, 2) */
395 args[0] = jerry_create_number (4);
396 args[1] = jerry_create_number (2);
397 res = jerry_call_function (val_foo, jerry_create_undefined (), args, 2);
398 TEST_ASSERT (!jerry_value_is_error (res));
399 TEST_ASSERT (jerry_value_is_number (res)
400 && jerry_get_number_value (res) == 1.0);
401 jerry_release_value (res);
402
403 /* Get global.bar */
404 val_bar = get_property (global_obj_val, "bar");
405 TEST_ASSERT (!jerry_value_is_error (val_bar));
406 TEST_ASSERT (jerry_value_is_object (val_bar));
407
408 /* Call bar (4, 2) */
409 res = jerry_call_function (val_bar, jerry_create_undefined (), args, 2);
410 TEST_ASSERT (!jerry_value_is_error (res));
411 TEST_ASSERT (jerry_value_is_number (res)
412 && jerry_get_number_value (res) == 5.0);
413 jerry_release_value (res);
414 jerry_release_value (val_bar);
415
416 /* Set global.t = "abcd" */
417 jerry_release_value (args[0]);
418 args[0] = jerry_create_string ((jerry_char_t *) "abcd");
419 res = set_property (global_obj_val, "t", args[0]);
420 TEST_ASSERT (!jerry_value_is_error (res));
421 TEST_ASSERT (jerry_get_boolean_value (res));
422 jerry_release_value (res);
423
424 /* Call foo (4, 2) */
425 res = jerry_call_function (val_foo, jerry_create_undefined (), args, 2);
426 TEST_ASSERT (!jerry_value_is_error (res));
427 TEST_ASSERT (jerry_value_is_string (res));
428 sz = jerry_get_string_size (res);
429 TEST_ASSERT (sz == 4);
430 sz = jerry_string_to_char_buffer (res, (jerry_char_t *) buffer, sz);
431 TEST_ASSERT (sz == 4);
432 jerry_release_value (res);
433 TEST_ASSERT (!strncmp (buffer, "abcd", (size_t) sz));
434 jerry_release_value (args[0]);
435 jerry_release_value (args[1]);
436
437 /* Get global.A */
438 val_A = get_property (global_obj_val, "A");
439 TEST_ASSERT (!jerry_value_is_error (val_A));
440 TEST_ASSERT (jerry_value_is_object (val_A));
441
442 /* Get A.prototype */
443 is_ok = jerry_value_is_constructor (val_A);
444 TEST_ASSERT (is_ok);
445 val_A_prototype = get_property (val_A, "prototype");
446 TEST_ASSERT (!jerry_value_is_error (val_A_prototype));
447 TEST_ASSERT (jerry_value_is_object (val_A_prototype));
448 jerry_release_value (val_A);
449
450 /* Set A.prototype.foo = global.foo */
451 res = set_property (val_A_prototype, "foo", val_foo);
452 TEST_ASSERT (!jerry_value_is_error (res));
453 TEST_ASSERT (jerry_get_boolean_value (res));
454 jerry_release_value (res);
455 jerry_release_value (val_A_prototype);
456 jerry_release_value (val_foo);
457
458 /* Get global.a */
459 val_a = get_property (global_obj_val, "a");
460 TEST_ASSERT (!jerry_value_is_error (val_a));
461 TEST_ASSERT (jerry_value_is_object (val_a));
462
463 /* Get a.t */
464 res = get_property (val_a, "t");
465 TEST_ASSERT (!jerry_value_is_error (res));
466 TEST_ASSERT (jerry_value_is_number (res)
467 && jerry_get_number_value (res) == 12.0);
468 jerry_release_value (res);
469
470 /* foreach properties */
471 val_p = get_property (global_obj_val, "p");
472 is_ok = jerry_foreach_object_property (val_p, foreach, (void *) "user_data");
473 TEST_ASSERT (is_ok);
474
475 /* break foreach at third element */
476 int count = 0;
477 is_ok = jerry_foreach_object_property (val_p, foreach_subset, &count);
478 TEST_ASSERT (is_ok);
479 TEST_ASSERT (count == 3);
480 jerry_release_value (val_p);
481
482 /* foreach with throw test */
483 val_np = get_property (global_obj_val, "np");
484 is_ok = !jerry_foreach_object_property (val_np, foreach_exception, NULL);
485 TEST_ASSERT (is_ok);
486 jerry_release_value (val_np);
487
488 /* Get a.foo */
489 val_a_foo = get_property (val_a, "foo");
490 TEST_ASSERT (!jerry_value_is_error (val_a_foo));
491 TEST_ASSERT (jerry_value_is_object (val_a_foo));
492
493 /* Call a.foo () */
494 res = jerry_call_function (val_a_foo, val_a, NULL, 0);
495 TEST_ASSERT (!jerry_value_is_error (res));
496 TEST_ASSERT (jerry_value_is_number (res)
497 && jerry_get_number_value (res) == 12.0);
498 jerry_release_value (res);
499 jerry_release_value (val_a_foo);
500
501 jerry_release_value (val_a);
502
503 /* Create native handler bound function object and set it to 'external' variable */
504 external_func_val = jerry_create_external_function (handler);
505 TEST_ASSERT (jerry_value_is_function (external_func_val)
506 && jerry_value_is_constructor (external_func_val));
507
508 res = set_property (global_obj_val, "external", external_func_val);
509 TEST_ASSERT (!jerry_value_is_error (res));
510 TEST_ASSERT (jerry_get_boolean_value (res));
511 jerry_release_value (external_func_val);
512
513 /* Call 'call_external' function that should call external function created above */
514 val_call_external = get_property (global_obj_val, "call_external");
515 TEST_ASSERT (!jerry_value_is_error (val_call_external));
516 TEST_ASSERT (jerry_value_is_object (val_call_external));
517 res = jerry_call_function (val_call_external, global_obj_val, NULL, 0);
518 jerry_release_value (val_call_external);
519 TEST_ASSERT (!jerry_value_is_error (res));
520 TEST_ASSERT (jerry_value_is_string (res));
521 sz = jerry_get_string_size (res);
522 TEST_ASSERT (sz == 19);
523 sz = jerry_string_to_char_buffer (res, (jerry_char_t *) buffer, sz);
524 TEST_ASSERT (sz == 19);
525 jerry_release_value (res);
526 TEST_ASSERT (!strncmp (buffer, "string from handler", (size_t) sz));
527
528 /* Create native handler bound function object and set it to 'external_construct' variable */
529 external_construct_val = jerry_create_external_function (handler_construct);
530 TEST_ASSERT (jerry_value_is_function (external_construct_val)
531 && jerry_value_is_constructor (external_construct_val));
532
533 res = set_property (global_obj_val, "external_construct", external_construct_val);
534 TEST_ASSERT (!jerry_value_is_error (res));
535 TEST_ASSERT (jerry_get_boolean_value (res));
536 jerry_release_value (res);
537
538 /* Call external function created above, as constructor */
539 args[0] = jerry_create_boolean (true);
540 res = jerry_construct_object (external_construct_val, args, 1);
541 TEST_ASSERT (!jerry_value_is_error (res));
542 TEST_ASSERT (jerry_value_is_object (res));
543 val_value_field = get_property (res, "value_field");
544
545 /* Get 'value_field' of constructed object */
546 TEST_ASSERT (!jerry_value_is_error (val_value_field));
547 TEST_ASSERT (jerry_value_is_boolean (val_value_field)
548 && jerry_get_boolean_value (val_value_field));
549 jerry_release_value (val_value_field);
550 jerry_release_value (external_construct_val);
551
552 void *ptr = NULL;
553 is_ok = jerry_get_object_native_pointer (res, &ptr, &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind2));
554 TEST_ASSERT (is_ok
555 && (uintptr_t) ptr == (uintptr_t) 0x0012345678abcdefull);
556
557 /* Passing NULL for info_p is allowed. */
558 is_ok = jerry_get_object_native_pointer (res, &ptr, NULL);
559 TEST_ASSERT (!is_ok);
560
561 jerry_release_value (res);
562
563 /* Test: It is ok to set native pointer's free callback as NULL. */
564 jerry_value_t obj_freecb = jerry_create_object ();
565 jerry_set_object_native_pointer (obj_freecb,
566 (void *) 0x1234,
567 &JERRY_NATIVE_HANDLE_INFO_FOR_CTYPE (bind3));
568
569 jerry_release_value (obj_freecb);
570
571 /* Test: Throwing exception from native handler. */
572 throw_test_handler_val = jerry_create_external_function (handler_throw_test);
573 TEST_ASSERT (jerry_value_is_function (throw_test_handler_val));
574
575 res = set_property (global_obj_val, "throw_test", throw_test_handler_val);
576 TEST_ASSERT (!jerry_value_is_error (res));
577 TEST_ASSERT (jerry_get_boolean_value (res));
578 jerry_release_value (res);
579 jerry_release_value (throw_test_handler_val);
580
581 val_t = get_property (global_obj_val, "call_throw_test");
582 TEST_ASSERT (!jerry_value_is_error (val_t));
583 TEST_ASSERT (jerry_value_is_object (val_t));
584
585 res = jerry_call_function (val_t, global_obj_val, NULL, 0);
586 TEST_ASSERT (!jerry_value_is_error (res));
587 jerry_release_value (val_t);
588 jerry_release_value (res);
589
590 /* Test: Unhandled exception in called function */
591 val_t = get_property (global_obj_val, "throw_reference_error");
592 TEST_ASSERT (!jerry_value_is_error (val_t));
593 TEST_ASSERT (jerry_value_is_object (val_t));
594
595 res = jerry_call_function (val_t, global_obj_val, NULL, 0);
596
597 TEST_ASSERT (jerry_value_is_error (res));
598 jerry_release_value (val_t);
599
600 /* 'res' should contain exception object */
601 res = jerry_get_value_from_error (res, true);
602 TEST_ASSERT (jerry_value_is_object (res));
603 jerry_release_value (res);
604
605 /* Test: Call of non-function */
606 obj_val = jerry_create_object ();
607 res = jerry_call_function (obj_val, global_obj_val, NULL, 0);
608 TEST_ASSERT (jerry_value_is_error (res));
609
610 /* 'res' should contain exception object */
611 res = jerry_get_value_from_error (res, true);
612 TEST_ASSERT (jerry_value_is_object (res));
613 jerry_release_value (res);
614
615 jerry_release_value (obj_val);
616
617 /* Test: Unhandled exception in function called, as constructor */
618 val_t = get_property (global_obj_val, "throw_reference_error");
619 TEST_ASSERT (!jerry_value_is_error (val_t));
620 TEST_ASSERT (jerry_value_is_object (val_t));
621
622 res = jerry_construct_object (val_t, NULL, 0);
623 TEST_ASSERT (jerry_value_is_error (res));
624 jerry_release_value (val_t);
625
626 /* 'res' should contain exception object */
627 res = jerry_get_value_from_error (res, true);
628 TEST_ASSERT (jerry_value_is_object (res));
629 jerry_release_value (res);
630
631 /* Test: Call of non-function as constructor */
632 obj_val = jerry_create_object ();
633 res = jerry_construct_object (obj_val, NULL, 0);
634 TEST_ASSERT (jerry_value_is_error (res));
635
636 /* 'res' should contain exception object */
637 res = jerry_get_value_from_error (res, true);
638 TEST_ASSERT (jerry_value_is_object (res));
639 jerry_release_value (res);
640
641 jerry_release_value (obj_val);
642
643 /* Test: Array Object API */
644 jerry_value_t array_obj_val = jerry_create_array (10);
645 TEST_ASSERT (jerry_value_is_array (array_obj_val));
646 TEST_ASSERT (jerry_get_array_length (array_obj_val) == 10);
647
648 jerry_value_t v_in = jerry_create_number (10.5);
649 res = jerry_set_property_by_index (array_obj_val, 5, v_in);
650 TEST_ASSERT (!jerry_value_is_error (res));
651 TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res));
652 jerry_release_value (res);
653 jerry_value_t v_out = jerry_get_property_by_index (array_obj_val, 5);
654
655 TEST_ASSERT (jerry_value_is_number (v_out)
656 && jerry_get_number_value (v_out) == 10.5);
657
658 jerry_delete_property_by_index (array_obj_val, 5);
659 jerry_value_t v_und = jerry_get_property_by_index (array_obj_val, 5);
660
661 TEST_ASSERT (jerry_value_is_undefined (v_und));
662
663 jerry_release_value (v_in);
664 jerry_release_value (v_out);
665 jerry_release_value (v_und);
666 jerry_release_value (array_obj_val);
667
668 /* Test: object keys */
669 res = jerry_get_object_keys (global_obj_val);
670 TEST_ASSERT (!jerry_value_is_error (res));
671 TEST_ASSERT (jerry_value_is_array (res));
672 TEST_ASSERT (jerry_get_array_length (res) == 15);
673 jerry_release_value (res);
674
675 /* Test: jerry_value_to_primitive */
676 obj_val = jerry_eval ((jerry_char_t *) "new String ('hello')", 20, JERRY_PARSE_NO_OPTS);
677 TEST_ASSERT (!jerry_value_is_error (obj_val));
678 TEST_ASSERT (jerry_value_is_object (obj_val));
679 TEST_ASSERT (!jerry_value_is_string (obj_val));
680 prim_val = jerry_value_to_primitive (obj_val);
681 TEST_ASSERT (!jerry_value_is_error (prim_val));
682 TEST_ASSERT (jerry_value_is_string (prim_val));
683 jerry_release_value (prim_val);
684
685 /* Test: jerry_get_prototype */
686 proto_val = jerry_get_prototype (jerry_create_undefined ());
687 TEST_ASSERT (jerry_value_is_error (proto_val));
688 jerry_value_t error = jerry_get_value_from_error (proto_val, true);
689 TEST_ASSERT (jerry_get_error_type (error) == JERRY_ERROR_TYPE);
690 jerry_release_value (error);
691
692 proto_val = jerry_get_prototype (obj_val);
693 TEST_ASSERT (!jerry_value_is_error (proto_val));
694 TEST_ASSERT (jerry_value_is_object (proto_val));
695 jerry_release_value (proto_val);
696 jerry_release_value (obj_val);
697
698 if (jerry_is_feature_enabled (JERRY_FEATURE_PROXY))
699 {
700 jerry_value_t target = jerry_create_object ();
701 jerry_value_t handler = jerry_create_object ();
702 jerry_value_t proxy = jerry_create_proxy (target, handler);
703 jerry_value_t obj_proto = jerry_eval ((jerry_char_t *) "Object.prototype", 16, JERRY_PARSE_NO_OPTS);
704
705 jerry_release_value (target);
706 jerry_release_value (handler);
707 proto_val = jerry_get_prototype (proxy);
708 TEST_ASSERT (!jerry_value_is_error (proto_val));
709 TEST_ASSERT (proto_val == obj_proto);
710 jerry_release_value (proto_val);
711 jerry_release_value (obj_proto);
712 jerry_release_value (proxy);
713 }
714
715 /* Test: jerry_set_prototype */
716 obj_val = jerry_create_object ();
717 res = jerry_set_prototype (obj_val, jerry_create_null ());
718 TEST_ASSERT (!jerry_value_is_error (res));
719 TEST_ASSERT (jerry_value_is_boolean (res));
720 TEST_ASSERT (jerry_get_boolean_value (res));
721
722 jerry_value_t new_proto = jerry_create_object ();
723 res = jerry_set_prototype (obj_val, new_proto);
724 jerry_release_value (new_proto);
725 TEST_ASSERT (!jerry_value_is_error (res));
726 TEST_ASSERT (jerry_value_is_boolean (res));
727 TEST_ASSERT (jerry_get_boolean_value (res));
728 proto_val = jerry_get_prototype (obj_val);
729 TEST_ASSERT (!jerry_value_is_error (proto_val));
730 TEST_ASSERT (jerry_value_is_object (proto_val));
731 jerry_release_value (proto_val);
732 jerry_release_value (obj_val);
733
734 if (jerry_is_feature_enabled (JERRY_FEATURE_PROXY))
735 {
736 jerry_value_t target = jerry_create_object ();
737 jerry_value_t handler = jerry_create_object ();
738 jerry_value_t proxy = jerry_create_proxy (target, handler);
739 new_proto = jerry_eval ((jerry_char_t *) "Function.prototype", 18, JERRY_PARSE_NO_OPTS);
740
741 res = jerry_set_prototype (proxy, new_proto);
742 TEST_ASSERT (!jerry_value_is_error (res));
743 jerry_value_t target_proto = jerry_get_prototype (target);
744 TEST_ASSERT (target_proto == new_proto);
745
746 jerry_release_value (target);
747 jerry_release_value (handler);
748 jerry_release_value (proxy);
749 jerry_release_value (new_proto);
750 jerry_release_value (target_proto);
751 }
752
753 /* Test: eval */
754 const jerry_char_t eval_code_src1[] = "(function () { return 123; })";
755 val_t = jerry_eval (eval_code_src1, sizeof (eval_code_src1) - 1, JERRY_PARSE_STRICT_MODE);
756 TEST_ASSERT (!jerry_value_is_error (val_t));
757 TEST_ASSERT (jerry_value_is_object (val_t));
758 TEST_ASSERT (jerry_value_is_function (val_t));
759
760 res = jerry_call_function (val_t, jerry_create_undefined (), NULL, 0);
761 TEST_ASSERT (!jerry_value_is_error (res));
762 TEST_ASSERT (jerry_value_is_number (res)
763 && jerry_get_number_value (res) == 123.0);
764 jerry_release_value (res);
765
766 jerry_release_value (val_t);
767
768 /* cleanup. */
769 jerry_release_value (global_obj_val);
770
771 /* Test: run gc. */
772 jerry_gc (JERRY_GC_PRESSURE_LOW);
773
774 /* Test: spaces */
775 const jerry_char_t eval_code_src2[] = "\x0a \x0b \x0c \xc2\xa0 \xe2\x80\xa8 \xe2\x80\xa9 \xef\xbb\xbf 4321";
776 val_t = jerry_eval (eval_code_src2, sizeof (eval_code_src2) - 1, JERRY_PARSE_STRICT_MODE);
777 TEST_ASSERT (!jerry_value_is_error (val_t));
778 TEST_ASSERT (jerry_value_is_number (val_t)
779 && jerry_get_number_value (val_t) == 4321.0);
780 jerry_release_value (val_t);
781
782 /* Test: number */
783 val_t = jerry_create_number (6.25);
784 number_val = jerry_get_number_value (val_t);
785 TEST_ASSERT (number_val * 3 == 18.75);
786 jerry_release_value (val_t);
787
788 val_t = jerry_create_number_infinity (true);
789 number_val = jerry_get_number_value (val_t);
790 TEST_ASSERT (number_val * 3 == number_val && number_val != 0.0);
791 jerry_release_value (val_t);
792
793 val_t = jerry_create_number_nan ();
794 number_val = jerry_get_number_value (val_t);
795 TEST_ASSERT (number_val != number_val);
796 jerry_release_value (val_t);
797
798 /* Test: create function */
799 const jerry_char_t func_resource[] = "unknown";
800 const jerry_char_t func_arg_list[] = "a , b,c";
801 const jerry_char_t func_src[] = " return 5 + a+\nb+c";
802
803 jerry_value_t func_val = jerry_parse_function (func_resource,
804 sizeof (func_resource) - 1,
805 func_arg_list,
806 sizeof (func_arg_list) - 1,
807 func_src,
808 sizeof (func_src) - 1,
809 JERRY_PARSE_NO_OPTS);
810
811 TEST_ASSERT (!jerry_value_is_error (func_val));
812
813 jerry_value_t func_args[3] =
814 {
815 jerry_create_number (4),
816 jerry_create_number (6),
817 jerry_create_number (-2)
818 };
819
820 val_t = jerry_call_function (func_val, func_args[0], func_args, 3);
821 number_val = jerry_get_number_value (val_t);
822 TEST_ASSERT (number_val == 13.0);
823
824 jerry_release_value (val_t);
825 jerry_release_value (func_val);
826
827 jerry_cleanup ();
828
829 TEST_ASSERT (test_api_is_free_callback_was_called);
830
831 /* Test: jerry_get_value_from_error */
832 {
833 jerry_init (JERRY_INIT_EMPTY);
834 jerry_value_t num_val = jerry_create_number (123);
835 num_val = jerry_create_error_from_value (num_val, true);
836 TEST_ASSERT (jerry_value_is_error (num_val));
837 jerry_value_t num2_val = jerry_get_value_from_error (num_val, false);
838 TEST_ASSERT (jerry_value_is_error (num_val));
839 TEST_ASSERT (!jerry_value_is_error (num2_val));
840 double num = jerry_get_number_value (num2_val);
841 TEST_ASSERT (num == 123);
842 num2_val = jerry_get_value_from_error (num_val, true);
843 TEST_ASSERT (!jerry_value_is_error (num2_val));
844 num = jerry_get_number_value (num2_val);
845 TEST_ASSERT (num == 123);
846 jerry_release_value (num2_val);
847 jerry_cleanup ();
848 }
849
850 /* Test parsing/executing scripts with lexically scoped global variables multiple times. */
851 if (jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL))
852 {
853 jerry_init (JERRY_INIT_EMPTY);
854 const jerry_char_t scoped_src_p[] = "let a;";
855 jerry_value_t parse_result = jerry_parse (NULL,
856 0,
857 scoped_src_p,
858 sizeof (scoped_src_p) - 1,
859 JERRY_PARSE_NO_OPTS);
860 TEST_ASSERT (!jerry_value_is_error (parse_result));
861 jerry_release_value (parse_result);
862
863 parse_result = jerry_parse (NULL,
864 0,
865 scoped_src_p,
866 sizeof (scoped_src_p) - 1,
867 JERRY_PARSE_NO_OPTS);
868 TEST_ASSERT (!jerry_value_is_error (parse_result));
869
870 jerry_value_t run_result = jerry_run (parse_result);
871 TEST_ASSERT (!jerry_value_is_error (run_result));
872 jerry_release_value (run_result);
873
874 /* Should be a syntax error due to redeclaration. */
875 run_result = jerry_run (parse_result);
876 TEST_ASSERT (jerry_value_is_error (run_result));
877 jerry_release_value (run_result);
878 jerry_release_value (parse_result);
879
880 /* The variable should have no effect on parsing. */
881 parse_result = jerry_parse (NULL,
882 0,
883 scoped_src_p,
884 sizeof (scoped_src_p) - 1,
885 JERRY_PARSE_NO_OPTS);
886 TEST_ASSERT (!jerry_value_is_error (parse_result));
887 jerry_release_value (parse_result);
888 jerry_cleanup ();
889 }
890
891 /* Test: parser error location */
892 if (jerry_is_feature_enabled (JERRY_FEATURE_ERROR_MESSAGES))
893 {
894 jerry_init (JERRY_INIT_SHOW_OPCODES);
895
896 const jerry_char_t parser_err_src[] = "b = 'hello';\nvar a = (;";
897 parsed_code_val = jerry_parse (NULL,
898 0,
899 parser_err_src,
900 sizeof (parser_err_src) - 1,
901 JERRY_PARSE_NO_OPTS);
902 TEST_ASSERT (jerry_value_is_error (parsed_code_val));
903 parsed_code_val = jerry_get_value_from_error (parsed_code_val, true);
904 jerry_value_t err_str_val = jerry_value_to_string (parsed_code_val);
905 jerry_size_t err_str_size = jerry_get_string_size (err_str_val);
906 jerry_char_t err_str_buf[256];
907 sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size);
908 err_str_buf[sz] = 0;
909
910 jerry_release_value (err_str_val);
911 jerry_release_value (parsed_code_val);
912 TEST_ASSERT (!strcmp ((char *) err_str_buf,
913 "SyntaxError: Primary expression expected. [<anonymous>:2:10]"));
914
915 const jerry_char_t file_str[] = "filename.js";
916 parsed_code_val = jerry_parse (file_str,
917 sizeof (file_str) - 1,
918 parser_err_src,
919 sizeof (parser_err_src) - 1,
920 JERRY_PARSE_NO_OPTS);
921 TEST_ASSERT (jerry_value_is_error (parsed_code_val));
922 parsed_code_val = jerry_get_value_from_error (parsed_code_val, true);
923 err_str_val = jerry_value_to_string (parsed_code_val);
924 err_str_size = jerry_get_string_size (err_str_val);
925
926 sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size);
927 err_str_buf[sz] = 0;
928
929 jerry_release_value (err_str_val);
930 jerry_release_value (parsed_code_val);
931 TEST_ASSERT (!strcmp ((char *) err_str_buf,
932 "SyntaxError: Primary expression expected. [filename.js:2:10]"));
933
934 const jerry_char_t eval_err_src[] = "eval(\"var b;\\nfor (,); \");";
935 parsed_code_val = jerry_parse (file_str,
936 sizeof (file_str),
937 eval_err_src,
938 sizeof (eval_err_src) - 1,
939 JERRY_PARSE_NO_OPTS);
940 TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
941
942 res = jerry_run (parsed_code_val);
943 TEST_ASSERT (jerry_value_is_error (res));
944 res = jerry_get_value_from_error (res, true);
945 err_str_val = jerry_value_to_string (res);
946 err_str_size = jerry_get_string_size (err_str_val);
947
948 sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size);
949 err_str_buf[sz] = 0;
950
951 jerry_release_value (err_str_val);
952 jerry_release_value (parsed_code_val);
953 jerry_release_value (res);
954 TEST_ASSERT (!strcmp ((char *) err_str_buf,
955 "SyntaxError: Primary expression expected. [<eval>:2:6]"));
956
957 jerry_cleanup ();
958 }
959
960 /* External Magic String */
961 jerry_init (JERRY_INIT_SHOW_OPCODES);
962
963 uint32_t num_magic_string_items = (uint32_t) (sizeof (magic_string_items) / sizeof (jerry_char_t *));
964 jerry_register_magic_strings (magic_string_items,
965 num_magic_string_items,
966 magic_string_lengths);
967
968 const jerry_char_t ms_code_src[] = "var global = {}; var console = [1]; var process = 1;";
969 parsed_code_val = jerry_parse (NULL,
970 0,
971 ms_code_src,
972 sizeof (ms_code_src) - 1,
973 JERRY_PARSE_NO_OPTS);
974 TEST_ASSERT (!jerry_value_is_error (parsed_code_val));
975
976 res = jerry_run (parsed_code_val);
977 TEST_ASSERT (!jerry_value_is_error (res));
978 jerry_release_value (res);
979 jerry_release_value (parsed_code_val);
980
981 /* call jerry_create_string functions which will returns with the registered external magic strings */
982 args[0] = jerry_create_string ((jerry_char_t *) "console");
983 args[1] = jerry_create_string ((jerry_char_t *) "\xed\xa0\x80\xed\xb6\x8a"); /**< greek zero sign */
984
985 cesu8_length = jerry_get_string_length (args[0]);
986 cesu8_sz = jerry_get_string_size (args[0]);
987
988 JERRY_VLA (char, string_console, cesu8_sz);
989 jerry_string_to_char_buffer (args[0], (jerry_char_t *) string_console, cesu8_sz);
990
991 TEST_ASSERT (!strncmp (string_console, "console", cesu8_sz));
992 TEST_ASSERT (cesu8_length == 7);
993 TEST_ASSERT (cesu8_length == cesu8_sz);
994
995 jerry_release_value (args[0]);
996
997 const jerry_char_t test_magic_str_access_src[] = "'console'.charAt(6) == 'e'";
998 res = jerry_eval (test_magic_str_access_src,
999 sizeof (test_magic_str_access_src) - 1,
1000 JERRY_PARSE_NO_OPTS);
1001 TEST_ASSERT (jerry_value_is_boolean (res));
1002 TEST_ASSERT (jerry_get_boolean_value (res) == true);
1003
1004 jerry_release_value (res);
1005
1006 cesu8_length = jerry_get_string_length (args[1]);
1007 cesu8_sz = jerry_get_string_size (args[1]);
1008
1009 JERRY_VLA (char, string_greek_zero_sign, cesu8_sz);
1010 jerry_string_to_char_buffer (args[1], (jerry_char_t *) string_greek_zero_sign, cesu8_sz);
1011
1012 TEST_ASSERT (!strncmp (string_greek_zero_sign, "\xed\xa0\x80\xed\xb6\x8a", cesu8_sz));
1013 TEST_ASSERT (cesu8_length == 2);
1014 TEST_ASSERT (cesu8_sz == 6);
1015
1016 jerry_release_value (args[1]);
1017
1018 {
1019 /*json parser check*/
1020 const char data_check[]="John";
1021 jerry_value_t key = jerry_create_string ((const jerry_char_t *) "name");
1022 const jerry_char_t data[] = "{\"name\": \"John\", \"age\": 5}";
1023 jerry_value_t parsed_json = jerry_json_parse (data, sizeof (data) - 1);
1024 jerry_value_t has_prop_js = jerry_has_property (parsed_json, key);
1025 TEST_ASSERT (jerry_get_boolean_value (has_prop_js));
1026 jerry_release_value (has_prop_js);
1027 jerry_value_t parsed_data = jerry_get_property (parsed_json, key);
1028 TEST_ASSERT (jerry_value_is_string (parsed_data) == true);
1029 jerry_size_t buff_size = jerry_get_string_size (parsed_data);
1030 JERRY_VLA (char, buff, buff_size + 1);
1031 jerry_string_to_char_buffer (parsed_data, (jerry_char_t *) buff, buff_size);
1032 buff[buff_size] = '\0';
1033 TEST_ASSERT (strcmp (data_check, buff) == false);
1034 jerry_release_value (parsed_json);
1035 jerry_release_value (key);
1036 jerry_release_value (parsed_data);
1037 }
1038
1039 /*json stringify test*/
1040 {
1041 jerry_value_t obj = jerry_create_object ();
1042 char check_value[] = "{\"name\":\"John\"}";
1043 jerry_value_t key = jerry_create_string ((const jerry_char_t *) "name");
1044 jerry_value_t value = jerry_create_string ((const jerry_char_t *) "John");
1045 res = jerry_set_property (obj, key, value);
1046 TEST_ASSERT (!jerry_value_is_error (res));
1047 TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res));
1048 jerry_release_value (res);
1049 jerry_value_t stringified = jerry_json_stringify (obj);
1050 TEST_ASSERT (jerry_value_is_string (stringified));
1051 jerry_size_t buff_size = jerry_get_string_size (stringified);
1052 JERRY_VLA (char, buff, buff_size + 1);
1053 jerry_string_to_char_buffer (stringified, (jerry_char_t *) buff, buff_size);
1054 buff[buff_size] = '\0';
1055 TEST_ASSERT (strcmp ((const char *) check_value, (const char *) buff) == 0);
1056 jerry_release_value (stringified);
1057 jerry_release_value (obj);
1058 jerry_release_value (key);
1059 jerry_release_value (value);
1060 }
1061 jerry_cleanup ();
1062
1063 return 0;
1064 } /* main */
1065