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