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 <stdio.h>
17#include <math.h>
18
19#include "debugger.h"
20#include "ecma-alloc.h"
21#include "ecma-array-object.h"
22#include "ecma-arraybuffer-object.h"
23#include "ecma-bigint.h"
24#include "ecma-builtin-helpers.h"
25#include "ecma-builtins.h"
26#include "ecma-comparison.h"
27#include "ecma-container-object.h"
28#include "ecma-dataview-object.h"
29#include "ecma-exceptions.h"
30#include "ecma-eval.h"
31#include "ecma-function-object.h"
32#include "ecma-gc.h"
33#include "ecma-helpers.h"
34#include "ecma-init-finalize.h"
35#include "ecma-lex-env.h"
36#include "lit-char-helpers.h"
37#include "ecma-literal-storage.h"
38#include "ecma-objects.h"
39#include "ecma-objects-general.h"
40#include "ecma-regexp-object.h"
41#include "ecma-promise-object.h"
42#include "ecma-proxy-object.h"
43#include "ecma-symbol-object.h"
44#include "ecma-typedarray-object.h"
45#include "opcodes.h"
46#include "jcontext.h"
47#include "jerryscript.h"
48#include "jerryscript-debugger-transport.h"
49#include "jmem.h"
50#include "js-parser.h"
51#include "re-compiler.h"
52
53JERRY_STATIC_ASSERT (sizeof (jerry_value_t) == sizeof (ecma_value_t),
54 size_of_jerry_value_t_must_be_equal_to_size_of_ecma_value_t);
55
56JERRY_STATIC_ASSERT ((int) ECMA_ERROR_NONE == (int) JERRY_ERROR_NONE
57 && (int) ECMA_ERROR_COMMON == (int) JERRY_ERROR_COMMON
58 && (int) ECMA_ERROR_EVAL == (int) JERRY_ERROR_EVAL
59 && (int) ECMA_ERROR_RANGE == (int) JERRY_ERROR_RANGE
60 && (int) ECMA_ERROR_REFERENCE == (int) JERRY_ERROR_REFERENCE
61 && (int) ECMA_ERROR_SYNTAX == (int) JERRY_ERROR_SYNTAX
62 && (int) ECMA_ERROR_TYPE == (int) JERRY_ERROR_TYPE
63 && (int) ECMA_ERROR_URI == (int) JERRY_ERROR_URI,
64 ecma_standard_error_t_must_be_equal_to_jerry_error_t);
65
66JERRY_STATIC_ASSERT ((int) ECMA_INIT_EMPTY == (int) JERRY_INIT_EMPTY
67 && (int) ECMA_INIT_SHOW_OPCODES == (int) JERRY_INIT_SHOW_OPCODES
68 && (int) ECMA_INIT_SHOW_REGEXP_OPCODES == (int) JERRY_INIT_SHOW_REGEXP_OPCODES
69 && (int) ECMA_INIT_MEM_STATS == (int) JERRY_INIT_MEM_STATS,
70 ecma_init_flag_t_must_be_equal_to_jerry_init_flag_t);
71
72#if ENABLED (JERRY_BUILTIN_REGEXP)
73JERRY_STATIC_ASSERT ((int) RE_FLAG_GLOBAL == (int) JERRY_REGEXP_FLAG_GLOBAL
74 && (int) RE_FLAG_MULTILINE == (int) JERRY_REGEXP_FLAG_MULTILINE
75 && (int) RE_FLAG_IGNORE_CASE == (int) JERRY_REGEXP_FLAG_IGNORE_CASE
76 && (int) RE_FLAG_STICKY== (int) JERRY_REGEXP_FLAG_STICKY
77 && (int) RE_FLAG_UNICODE == (int) JERRY_REGEXP_FLAG_UNICODE
78 && (int) RE_FLAG_DOTALL == (int) JERRY_REGEXP_FLAG_DOTALL,
79 re_flags_t_must_be_equal_to_jerry_regexp_flags_t);
80#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
81
82#if ENABLED (JERRY_BUILTIN_PROMISE)
83/* The internal ECMA_PROMISE_STATE_* values are "one byte away" from the API values */
84JERRY_STATIC_ASSERT ((int) ECMA_PROMISE_IS_PENDING == (int) JERRY_PROMISE_STATE_PENDING
85 && (int) ECMA_PROMISE_IS_FULFILLED == (int) JERRY_PROMISE_STATE_FULFILLED,
86 promise_internal_state_matches_external);
87#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
88
89/**
90 * Offset between internal and external arithmetic operator types
91 */
92#define ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET (JERRY_BIN_OP_SUB - NUMBER_ARITHMETIC_SUBTRACTION)
93
94JERRY_STATIC_ASSERT (((NUMBER_ARITHMETIC_SUBTRACTION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_SUB)
95 && ((NUMBER_ARITHMETIC_MULTIPLICATION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_MUL)
96 && ((NUMBER_ARITHMETIC_DIVISION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_DIV)
97 && ((NUMBER_ARITHMETIC_REMAINDER + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_REM),
98 number_arithmetics_operation_type_matches_external);
99
100#if !ENABLED (JERRY_PARSER) && !ENABLED (JERRY_SNAPSHOT_EXEC)
101#error "JERRY_SNAPSHOT_EXEC must be enabled if JERRY_PARSER is disabled!"
102#endif /* !ENABLED (JERRY_PARSER) && !ENABLED (JERRY_SNAPSHOT_EXEC) */
103
104#if ENABLED (JERRY_ERROR_MESSAGES)
105
106/**
107 * Error message, if an argument is has an error flag
108 */
109static const char * const error_value_msg_p = "argument cannot have an error flag";
110
111/**
112 * Error message, if types of arguments are incorrect
113 */
114static const char * const wrong_args_msg_p = "wrong type of argument";
115
116#if !ENABLED (JERRY_BUILTIN_BIGINT)
117
118/**
119 * Error message, if BigInt support is disabled
120 */
121static const char * const error_bigint_not_supported_p = "BigInt support is disabled";
122
123#endif /* !ENABLED (JERRY_BUILTIN_BIGINT) */
124
125#endif /* ENABLED (JERRY_ERROR_MESSAGES) */
126
127/** \addtogroup jerry Jerry engine interface
128 * @{
129 */
130
131/**
132 * Assert that it is correct to call API in current state.
133 *
134 * Note:
135 * By convention, there are some states when API could not be invoked.
136 *
137 * The API can be and only be invoked when the ECMA_STATUS_API_AVAILABLE
138 * flag is set.
139 *
140 * This procedure checks whether the API is available, and terminates
141 * the engine if it is unavailable. Otherwise it is a no-op.
142 *
143 * Note:
144 * The API could not be invoked in the following cases:
145 * - before jerry_init and after jerry_cleanup
146 * - between enter to and return from a native free callback
147 */
148static inline void JERRY_ATTR_ALWAYS_INLINE
149jerry_assert_api_available (void)
150{
151 JERRY_ASSERT (JERRY_CONTEXT (status_flags) & ECMA_STATUS_API_AVAILABLE);
152} /* jerry_assert_api_available */
153
154/**
155 * Turn on API availability
156 */
157static inline void JERRY_ATTR_ALWAYS_INLINE
158jerry_make_api_available (void)
159{
160 JERRY_CONTEXT (status_flags) |= ECMA_STATUS_API_AVAILABLE;
161} /* jerry_make_api_available */
162
163/**
164 * Turn off API availability
165 */
166static inline void JERRY_ATTR_ALWAYS_INLINE
167jerry_make_api_unavailable (void)
168{
169 JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_API_AVAILABLE;
170} /* jerry_make_api_unavailable */
171
172/**
173 * Create an API compatible return value.
174 *
175 * @return return value for Jerry API functions
176 */
177static jerry_value_t
178jerry_return (jerry_value_t value) /**< return value */
179{
180 if (ECMA_IS_VALUE_ERROR (value))
181 {
182 value = ecma_create_error_reference_from_context ();
183 }
184
185 return value;
186} /* jerry_return */
187
188/**
189 * Throw an API compatible return value.
190 *
191 * @return return value for Jerry API functions
192 */
193static inline jerry_value_t JERRY_ATTR_ALWAYS_INLINE
194jerry_throw (jerry_value_t value) /**< return value */
195{
196 JERRY_ASSERT (ECMA_IS_VALUE_ERROR (value));
197 return ecma_create_error_reference_from_context ();
198} /* jerry_throw */
199
200/**
201 * Jerry engine initialization
202 */
203void
204jerry_init (jerry_init_flag_t flags) /**< combination of Jerry flags */
205{
206 /* This function cannot be called twice unless jerry_cleanup is called. */
207 JERRY_ASSERT (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_API_AVAILABLE));
208
209 /* Zero out all non-external members. */
210 memset ((char *) &JERRY_CONTEXT_STRUCT + offsetof (jerry_context_t, JERRY_CONTEXT_FIRST_MEMBER), 0,
211 sizeof (jerry_context_t) - offsetof (jerry_context_t, JERRY_CONTEXT_FIRST_MEMBER));
212
213 JERRY_CONTEXT (jerry_init_flags) = flags;
214
215 jerry_make_api_available ();
216
217 jmem_init ();
218 ecma_init ();
219} /* jerry_init */
220
221/**
222 * Terminate Jerry engine
223 */
224void
225jerry_cleanup (void)
226{
227 jerry_assert_api_available ();
228
229#if ENABLED (JERRY_DEBUGGER)
230 if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
231 {
232 jerry_debugger_send_type (JERRY_DEBUGGER_CLOSE_CONNECTION);
233
234 jerry_debugger_transport_close ();
235 }
236#endif /* ENABLED (JERRY_DEBUGGER) */
237
238 for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p);
239 this_p != NULL;
240 this_p = this_p->next_p)
241 {
242 if (this_p->manager_p->deinit_cb)
243 {
244 void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL;
245 this_p->manager_p->deinit_cb (data);
246 }
247 }
248
249#if ENABLED (JERRY_BUILTIN_PROMISE)
250 ecma_free_all_enqueued_jobs ();
251#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
252 ecma_finalize ();
253 jerry_make_api_unavailable ();
254
255 for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p), *next_p = NULL;
256 this_p != NULL;
257 this_p = next_p)
258 {
259 next_p = this_p->next_p;
260 if (this_p->manager_p->finalize_cb)
261 {
262 void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL;
263 this_p->manager_p->finalize_cb (data);
264 }
265 jmem_heap_free_block (this_p, sizeof (jerry_context_data_header_t) + this_p->manager_p->bytes_needed);
266 }
267
268 jmem_finalize ();
269} /* jerry_cleanup */
270
271/**
272 * Retrieve a context data item, or create a new one.
273 *
274 * @param manager_p pointer to the manager whose context data item should be returned.
275 *
276 * @return a pointer to the user-provided context-specific data item for the given manager, creating such a pointer if
277 * none was found.
278 */
279void *
280jerry_get_context_data (const jerry_context_data_manager_t *manager_p)
281{
282 void *ret = NULL;
283 jerry_context_data_header_t *item_p;
284
285 for (item_p = JERRY_CONTEXT (context_data_p); item_p != NULL; item_p = item_p->next_p)
286 {
287 if (item_p->manager_p == manager_p)
288 {
289 return (manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p) : NULL;
290 }
291 }
292
293 item_p = jmem_heap_alloc_block (sizeof (jerry_context_data_header_t) + manager_p->bytes_needed);
294 item_p->manager_p = manager_p;
295 item_p->next_p = JERRY_CONTEXT (context_data_p);
296 JERRY_CONTEXT (context_data_p) = item_p;
297
298 if (manager_p->bytes_needed > 0)
299 {
300 ret = JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p);
301 memset (ret, 0, manager_p->bytes_needed);
302 }
303
304 if (manager_p->init_cb)
305 {
306 manager_p->init_cb (ret);
307 }
308
309 return ret;
310} /* jerry_get_context_data */
311
312/**
313 * Register external magic string array
314 */
315void
316jerry_register_magic_strings (const jerry_char_t * const *ex_str_items_p, /**< character arrays, representing
317 * external magic strings' contents */
318 uint32_t count, /**< number of the strings */
319 const jerry_length_t *str_lengths_p) /**< lengths of all strings */
320{
321 jerry_assert_api_available ();
322
323 lit_magic_strings_ex_set ((const lit_utf8_byte_t * const *) ex_str_items_p,
324 count,
325 (const lit_utf8_size_t *) str_lengths_p);
326} /* jerry_register_magic_strings */
327
328/**
329 * Run garbage collection
330 */
331void
332jerry_gc (jerry_gc_mode_t mode) /**< operational mode */
333{
334 jerry_assert_api_available ();
335
336 if (mode == JERRY_GC_PRESSURE_LOW)
337 {
338 /* Call GC directly, because 'ecma_free_unused_memory' might decide it's not yet worth it. */
339 ecma_gc_run ();
340 return;
341 }
342
343 ecma_free_unused_memory (JMEM_PRESSURE_HIGH);
344} /* jerry_gc */
345
346/**
347 * Get heap memory stats.
348 *
349 * @return true - get the heap stats successful
350 * false - otherwise. Usually it is because the MEM_STATS feature is not enabled.
351 */
352bool
353jerry_get_memory_stats (jerry_heap_stats_t *out_stats_p) /**< [out] heap memory stats */
354{
355#if ENABLED (JERRY_MEM_STATS)
356 if (out_stats_p == NULL)
357 {
358 return false;
359 }
360
361 jmem_heap_stats_t jmem_heap_stats;
362 memset (&jmem_heap_stats, 0, sizeof (jmem_heap_stats));
363 jmem_heap_get_stats (&jmem_heap_stats);
364
365 *out_stats_p = (jerry_heap_stats_t)
366 {
367 .version = 1,
368 .size = jmem_heap_stats.size,
369 .allocated_bytes = jmem_heap_stats.allocated_bytes,
370 .peak_allocated_bytes = jmem_heap_stats.peak_allocated_bytes
371 };
372
373 return true;
374#else /* !ENABLED (JERRY_MEM_STATS) */
375 JERRY_UNUSED (out_stats_p);
376 return false;
377#endif /* ENABLED (JERRY_MEM_STATS) */
378} /* jerry_get_memory_stats */
379
380/**
381 * Simple Jerry runner
382 *
383 * @return true - if run was successful
384 * false - otherwise
385 */
386bool
387jerry_run_simple (const jerry_char_t *script_source_p, /**< script source */
388 size_t script_source_size, /**< script source size */
389 jerry_init_flag_t flags) /**< combination of Jerry flags */
390{
391 bool result = false;
392
393 jerry_init (flags);
394
395 jerry_value_t parse_ret_val = jerry_parse (NULL, 0, script_source_p, script_source_size, JERRY_PARSE_NO_OPTS);
396
397 if (!ecma_is_value_error_reference (parse_ret_val))
398 {
399 jerry_value_t run_ret_val = jerry_run (parse_ret_val);
400
401 if (!ecma_is_value_error_reference (run_ret_val))
402 {
403 result = true;
404 }
405
406 jerry_release_value (run_ret_val);
407 }
408
409 jerry_release_value (parse_ret_val);
410 jerry_cleanup ();
411
412 return result;
413} /* jerry_run_simple */
414
415/**
416 * Parse script and construct an EcmaScript function. The lexical
417 * environment is set to the global lexical environment.
418 *
419 * @return function object value - if script was parsed successfully,
420 * thrown error - otherwise
421 */
422jerry_value_t
423jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a file name) */
424 size_t resource_name_length, /**< length of resource name */
425 const jerry_char_t *source_p, /**< script source */
426 size_t source_size, /**< script source size */
427 uint32_t parse_opts) /**< jerry_parse_opts_t option bits */
428{
429#if ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)
430 if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
431 && resource_name_length > 0)
432 {
433 jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
434 JERRY_DEBUGGER_NO_SUBTYPE,
435 resource_name_p,
436 resource_name_length);
437 }
438#else /* !(ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)) */
439 JERRY_UNUSED (resource_name_p);
440 JERRY_UNUSED (resource_name_length);
441#endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
442
443#if ENABLED (JERRY_PARSER)
444 jerry_assert_api_available ();
445
446 ecma_value_t resource_name = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
447
448#if ENABLED (JERRY_RESOURCE_NAME)
449 if (resource_name_length > 0)
450 {
451 resource_name = ecma_find_or_create_literal_string (resource_name_p, (lit_utf8_size_t) resource_name_length);
452 }
453#endif /* ENABLED (JERRY_RESOURCE_NAME) */
454
455 if ((parse_opts & JERRY_PARSE_MODULE) != 0)
456 {
457#if ENABLED (JERRY_MODULE_SYSTEM)
458 ecma_module_initialize_context (ecma_get_string_from_value (resource_name));
459#else /* !ENABLED (JERRY_MODULE_SYSTEM) */
460 return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("Module system has been disabled.")));
461#endif /* !ENABLED (JERRY_MODULE_SYSTEM) */
462 }
463
464 ecma_compiled_code_t *bytecode_data_p = parser_parse_script (NULL,
465 0,
466 source_p,
467 source_size,
468 resource_name,
469 parse_opts);
470
471 if (JERRY_UNLIKELY (bytecode_data_p == NULL))
472 {
473#if ENABLED (JERRY_MODULE_SYSTEM)
474 if ((parse_opts & JERRY_PARSE_MODULE) != 0)
475 {
476 ecma_module_cleanup_context ();
477 }
478#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
479
480 return ecma_create_error_reference_from_context ();
481 }
482
483#if ENABLED (JERRY_MODULE_SYSTEM)
484 if ((parse_opts & JERRY_PARSE_MODULE) != 0)
485 {
486 if (ECMA_IS_VALUE_ERROR (ecma_module_parse_referenced_modules ()))
487 {
488 ecma_bytecode_deref (bytecode_data_p);
489 ecma_module_cleanup_context ();
490
491 return ecma_create_error_reference_from_context ();
492 }
493
494 ecma_object_t *obj_p = ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS);
495
496 ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) obj_p;
497 wrapper_p->u.class_prop.class_id = LIT_MAGIC_STRING_RUNNABLE_UL;
498 wrapper_p->u.class_prop.extra_info = ECMA_RUNNABLE_FLAGS_MODULE;
499
500 ecma_module_t *root_module_p = JERRY_CONTEXT (module_current_p);
501 root_module_p->compiled_code_p = bytecode_data_p;
502
503 ECMA_SET_INTERNAL_VALUE_POINTER (wrapper_p->u.class_prop.u.value, root_module_p);
504 JERRY_CONTEXT (module_current_p) = NULL;
505 JERRY_CONTEXT (module_list_p) = NULL;
506
507 return ecma_make_object_value (obj_p);
508 }
509#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
510
511 ecma_object_t *global_object_p = ecma_builtin_get_global ();
512
513#if ENABLED (JERRY_BUILTIN_REALMS)
514 JERRY_ASSERT (global_object_p == (ecma_object_t *) ecma_op_function_get_realm (bytecode_data_p));
515#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
516
517 ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p);
518
519 /* TODO(dbatyai): For now Scripts continue to return Function objects due to backwards compatibility. This should be
520 * changed to also return a Runnable object eventually. */
521 ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
522 ecma_bytecode_deref (bytecode_data_p);
523
524 return ecma_make_object_value (func_obj_p);
525#else /* !ENABLED (JERRY_PARSER) */
526 JERRY_UNUSED (source_p);
527 JERRY_UNUSED (source_size);
528 JERRY_UNUSED (parse_opts);
529
530 return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled.")));
531#endif /* ENABLED (JERRY_PARSER) */
532} /* jerry_parse */
533
534/**
535 * Parse function and construct an EcmaScript function. The lexical
536 * environment is set to the global lexical environment.
537 *
538 * @return function object value - if script was parsed successfully,
539 * thrown error - otherwise
540 */
541jerry_value_t
542jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (usually a file name) */
543 size_t resource_name_length, /**< length of resource name */
544 const jerry_char_t *arg_list_p, /**< script source */
545 size_t arg_list_size, /**< script source size */
546 const jerry_char_t *source_p, /**< script source */
547 size_t source_size, /**< script source size */
548 uint32_t parse_opts) /**< jerry_parse_opts_t option bits */
549{
550#if ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)
551 if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
552 {
553 jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
554 JERRY_DEBUGGER_NO_SUBTYPE,
555 resource_name_p,
556 resource_name_length);
557 }
558#else /* !(ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)) */
559 JERRY_UNUSED (resource_name_p);
560 JERRY_UNUSED (resource_name_length);
561#endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
562
563#if ENABLED (JERRY_PARSER)
564 jerry_assert_api_available ();
565
566 ecma_value_t resource_name = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
567
568#if ENABLED (JERRY_RESOURCE_NAME)
569 if (resource_name_length > 0)
570 {
571 resource_name = ecma_find_or_create_literal_string (resource_name_p, (lit_utf8_size_t) resource_name_length);
572 }
573#endif /* ENABLED (JERRY_RESOURCE_NAME) */
574
575 if (arg_list_p == NULL)
576 {
577 /* Must not be a NULL value. */
578 arg_list_p = (const jerry_char_t *) "";
579 }
580
581 ecma_compiled_code_t *bytecode_p = parser_parse_script (arg_list_p,
582 arg_list_size,
583 source_p,
584 source_size,
585 resource_name,
586 parse_opts);
587
588 if (JERRY_UNLIKELY (bytecode_p == NULL))
589 {
590 return ecma_create_error_reference_from_context ();
591 }
592
593 ecma_object_t *global_object_p = ecma_builtin_get_global ();
594
595#if ENABLED (JERRY_BUILTIN_REALMS)
596 JERRY_ASSERT (global_object_p == (ecma_object_t *) ecma_op_function_get_realm (bytecode_p));
597#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
598
599 ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p);
600 ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_p);
601 ecma_bytecode_deref (bytecode_p);
602
603 return ecma_make_object_value (func_obj_p);
604#else /* !ENABLED (JERRY_PARSER) */
605 JERRY_UNUSED (arg_list_p);
606 JERRY_UNUSED (arg_list_size);
607 JERRY_UNUSED (source_p);
608 JERRY_UNUSED (source_size);
609 JERRY_UNUSED (parse_opts);
610
611 return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled.")));
612#endif /* ENABLED (JERRY_PARSER) */
613} /* jerry_parse_function */
614
615/**
616 * Run an EcmaScript function created by jerry_parse.
617 *
618 * Note:
619 * returned value must be freed with jerry_release_value, when it is no longer needed.
620 *
621 * @return result of bytecode - if run was successful
622 * thrown error - otherwise
623 */
624jerry_value_t
625jerry_run (const jerry_value_t func_val) /**< function to run */
626{
627 jerry_assert_api_available ();
628
629 if (!ecma_is_value_object (func_val))
630 {
631 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
632 }
633
634 ecma_object_t *obj_p = ecma_get_object_from_value (func_val);
635
636#if ENABLED (JERRY_MODULE_SYSTEM)
637 if (ecma_object_class_is (obj_p, LIT_MAGIC_STRING_RUNNABLE_UL))
638 {
639 ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) obj_p;
640 JERRY_ASSERT (wrapper_p->u.class_prop.extra_info == ECMA_RUNNABLE_FLAGS_MODULE);
641 ecma_module_t *root_module_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_module_t, wrapper_p->u.class_prop.u.value);
642
643#if ENABLED (JERRY_BUILTIN_REALMS)
644 ecma_object_t *global_object_p = (ecma_object_t *) ecma_op_function_get_realm (root_module_p->compiled_code_p);
645#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
646 ecma_object_t *global_object_p = ecma_builtin_get_global ();
647#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
648
649 ecma_create_global_lexical_block (global_object_p);
650 root_module_p->scope_p = ecma_get_global_scope (global_object_p);
651
652 return jerry_return (vm_run_module (root_module_p));
653 }
654#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
655
656 if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_FUNCTION
657 || ecma_get_object_is_builtin (obj_p))
658 {
659 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
660 }
661
662 ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p;
663
664 const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
665
666 if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) != CBC_FUNCTION_SCRIPT)
667 {
668 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
669 }
670
671 return jerry_return (vm_run_global (ecma_op_function_get_compiled_code (ext_func_p)));
672} /* jerry_run */
673
674/**
675 * Perform eval
676 *
677 * Note:
678 * returned value must be freed with jerry_release_value, when it is no longer needed.
679 *
680 * @return result of eval, may be error value.
681 */
682jerry_value_t
683jerry_eval (const jerry_char_t *source_p, /**< source code */
684 size_t source_size, /**< length of source code */
685 uint32_t parse_opts) /**< jerry_parse_opts_t option bits */
686{
687 jerry_assert_api_available ();
688
689 return jerry_return (ecma_op_eval_chars_buffer ((const lit_utf8_byte_t *) source_p,
690 source_size,
691 parse_opts));
692} /* jerry_eval */
693
694/**
695 * Run enqueued Promise jobs until the first thrown error or until all get executed.
696 *
697 * Note:
698 * returned value must be freed with jerry_release_value, when it is no longer needed.
699 *
700 * @return result of last executed job, may be error value.
701 */
702jerry_value_t
703jerry_run_all_enqueued_jobs (void)
704{
705 jerry_assert_api_available ();
706
707#if ENABLED (JERRY_BUILTIN_PROMISE)
708 return ecma_process_all_enqueued_jobs ();
709#else /* !ENABLED (JERRY_BUILTIN_PROMISE) */
710 return ECMA_VALUE_UNDEFINED;
711#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
712} /* jerry_run_all_enqueued_jobs */
713
714/**
715 * Get global object
716 *
717 * Note:
718 * returned value must be freed with jerry_release_value, when it is no longer needed.
719 *
720 * @return api value of global object
721 */
722jerry_value_t
723jerry_get_global_object (void)
724{
725 jerry_assert_api_available ();
726 ecma_object_t *global_obj_p = ecma_builtin_get_global ();
727 ecma_ref_object (global_obj_p);
728 return ecma_make_object_value (global_obj_p);
729} /* jerry_get_global_object */
730
731/**
732 * Check if the specified value is an abort value.
733 *
734 * @return true - if both the error and abort values are set,
735 * false - otherwise
736 */
737bool
738jerry_value_is_abort (const jerry_value_t value) /**< api value */
739{
740 jerry_assert_api_available ();
741
742 if (!ecma_is_value_error_reference (value))
743 {
744 return false;
745 }
746
747 ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value);
748
749 return ECMA_EXTENDED_PRIMITIVE_GET_TYPE (error_ref_p) == ECMA_EXTENDED_PRIMITIVE_ABORT;
750} /* jerry_value_is_abort */
751
752/**
753 * Check if the specified value is an array object value.
754 *
755 * @return true - if the specified value is an array object,
756 * false - otherwise
757 */
758bool
759jerry_value_is_array (const jerry_value_t value) /**< jerry api value */
760{
761 jerry_assert_api_available ();
762
763 return (ecma_is_value_object (value)
764 && ecma_get_object_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_TYPE_ARRAY);
765} /* jerry_value_is_array */
766
767/**
768 * Check if the specified value is boolean.
769 *
770 * @return true - if the specified value is boolean,
771 * false - otherwise
772 */
773bool
774jerry_value_is_boolean (const jerry_value_t value) /**< api value */
775{
776 jerry_assert_api_available ();
777
778 return ecma_is_value_boolean (value);
779} /* jerry_value_is_boolean */
780
781/**
782 * Check if the specified value is a constructor function object value.
783 *
784 * @return true - if the specified value is a function value that implements [[Construct]],
785 * false - otherwise
786 */
787bool
788jerry_value_is_constructor (const jerry_value_t value) /**< jerry api value */
789{
790 jerry_assert_api_available ();
791
792 return ecma_is_constructor (value);
793} /* jerry_value_is_constructor */
794
795/**
796 * Check if the specified value is an error or abort value.
797 *
798 * @return true - if the specified value is an error value,
799 * false - otherwise
800 */
801bool
802jerry_value_is_error (const jerry_value_t value) /**< api value */
803{
804 jerry_assert_api_available ();
805
806 return ecma_is_value_error_reference (value);
807} /* jerry_value_is_error */
808
809/**
810 * Check if the specified value is a function object value.
811 *
812 * @return true - if the specified value is callable,
813 * false - otherwise
814 */
815bool
816jerry_value_is_function (const jerry_value_t value) /**< api value */
817{
818 jerry_assert_api_available ();
819
820 return ecma_op_is_callable (value);
821} /* jerry_value_is_function */
822
823/**
824 * Check if the specified value is an async function object value.
825 *
826 * @return true - if the specified value is an async function,
827 * false - otherwise
828 */
829bool
830jerry_value_is_async_function (const jerry_value_t value) /**< api value */
831{
832 jerry_assert_api_available ();
833
834#if ENABLED (JERRY_ESNEXT)
835 if (ecma_is_value_object (value))
836 {
837 ecma_object_t *obj_p = ecma_get_object_from_value (value);
838
839 if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION
840 && !ecma_get_object_is_builtin (obj_p))
841 {
842 const ecma_compiled_code_t *bytecode_data_p;
843 bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) obj_p);
844 uint16_t type = CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags);
845
846 return (type == CBC_FUNCTION_ASYNC
847 || type == CBC_FUNCTION_ASYNC_ARROW
848 || type == CBC_FUNCTION_ASYNC_GENERATOR);
849 }
850 }
851#else /* !ENABLED (JERRY_ESNEXT) */
852 JERRY_UNUSED (value);
853#endif /* ENABLED (JERRY_ESNEXT) */
854
855 return false;
856} /* jerry_value_is_async_function */
857
858/**
859 * Check if the specified value is number.
860 *
861 * @return true - if the specified value is number,
862 * false - otherwise
863 */
864bool
865jerry_value_is_number (const jerry_value_t value) /**< api value */
866{
867 jerry_assert_api_available ();
868
869 return ecma_is_value_number (value);
870} /* jerry_value_is_number */
871
872/**
873 * Check if the specified value is null.
874 *
875 * @return true - if the specified value is null,
876 * false - otherwise
877 */
878bool
879jerry_value_is_null (const jerry_value_t value) /**< api value */
880{
881 jerry_assert_api_available ();
882
883 return ecma_is_value_null (value);
884} /* jerry_value_is_null */
885
886/**
887 * Check if the specified value is object.
888 *
889 * @return true - if the specified value is object,
890 * false - otherwise
891 */
892bool
893jerry_value_is_object (const jerry_value_t value) /**< api value */
894{
895 jerry_assert_api_available ();
896
897 return ecma_is_value_object (value);
898} /* jerry_value_is_object */
899
900/**
901 * Check if the specified value is promise.
902 *
903 * @return true - if the specified value is promise,
904 * false - otherwise
905 */
906bool
907jerry_value_is_promise (const jerry_value_t value) /**< api value */
908{
909 jerry_assert_api_available ();
910#if ENABLED (JERRY_BUILTIN_PROMISE)
911 return (ecma_is_value_object (value)
912 && ecma_is_promise (ecma_get_object_from_value (value)));
913#else /* !ENABLED (JERRY_BUILTIN_PROMISE) */
914 JERRY_UNUSED (value);
915 return false;
916#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
917} /* jerry_value_is_promise */
918
919/**
920 * Check if the specified value is a proxy object.
921 *
922 * @return true - if the specified value is a proxy object,
923 * false - otherwise
924 */
925bool
926jerry_value_is_proxy (const jerry_value_t value) /**< api value */
927{
928 jerry_assert_api_available ();
929#if ENABLED (JERRY_BUILTIN_PROXY)
930 return (ecma_is_value_object (value)
931 && ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (value)));
932#else /* !ENABLED (JERRY_BUILTIN_PROXY) */
933 JERRY_UNUSED (value);
934 return false;
935#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
936} /* jerry_value_is_proxy */
937
938/**
939 * Check if the specified value is string.
940 *
941 * @return true - if the specified value is string,
942 * false - otherwise
943 */
944bool
945jerry_value_is_string (const jerry_value_t value) /**< api value */
946{
947 jerry_assert_api_available ();
948
949 return ecma_is_value_string (value);
950} /* jerry_value_is_string */
951
952/**
953 * Check if the specified value is symbol.
954 *
955 * @return true - if the specified value is symbol,
956 * false - otherwise
957 */
958bool
959jerry_value_is_symbol (const jerry_value_t value) /**< api value */
960{
961 jerry_assert_api_available ();
962
963#if ENABLED (JERRY_ESNEXT)
964 return ecma_is_value_symbol (value);
965#else /* !ENABLED (JERRY_ESNEXT) */
966 JERRY_UNUSED (value);
967 return false;
968#endif /* ENABLED (JERRY_ESNEXT) */
969} /* jerry_value_is_symbol */
970
971/**
972 * Check if the specified value is BigInt.
973 *
974 * @return true - if the specified value is BigInt,
975 * false - otherwise
976 */
977bool
978jerry_value_is_bigint (const jerry_value_t value) /**< api value */
979{
980 jerry_assert_api_available ();
981
982#if ENABLED (JERRY_BUILTIN_BIGINT)
983 return ecma_is_value_bigint (value);
984#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
985 JERRY_UNUSED (value);
986 return false;
987#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
988} /* jerry_value_is_bigint */
989
990/**
991 * Check if the specified value is undefined.
992 *
993 * @return true - if the specified value is undefined,
994 * false - otherwise
995 */
996bool
997jerry_value_is_undefined (const jerry_value_t value) /**< api value */
998{
999 jerry_assert_api_available ();
1000
1001 return ecma_is_value_undefined (value);
1002} /* jerry_value_is_undefined */
1003
1004/**
1005 * Perform the base type of the JavaScript value.
1006 *
1007 * @return jerry_type_t value
1008 */
1009jerry_type_t
1010jerry_value_get_type (const jerry_value_t value) /**< input value to check */
1011{
1012 jerry_assert_api_available ();
1013
1014 if (ecma_is_value_error_reference (value))
1015 {
1016 return JERRY_TYPE_ERROR;
1017 }
1018
1019 lit_magic_string_id_t lit_id = ecma_get_typeof_lit_id (value);
1020
1021 JERRY_ASSERT (lit_id != LIT_MAGIC_STRING__EMPTY);
1022
1023 switch (lit_id)
1024 {
1025 case LIT_MAGIC_STRING_UNDEFINED:
1026 {
1027 return JERRY_TYPE_UNDEFINED;
1028 }
1029 case LIT_MAGIC_STRING_BOOLEAN:
1030 {
1031 return JERRY_TYPE_BOOLEAN;
1032 }
1033 case LIT_MAGIC_STRING_NUMBER:
1034 {
1035 return JERRY_TYPE_NUMBER;
1036 }
1037 case LIT_MAGIC_STRING_STRING:
1038 {
1039 return JERRY_TYPE_STRING;
1040 }
1041#if ENABLED (JERRY_ESNEXT)
1042 case LIT_MAGIC_STRING_SYMBOL:
1043 {
1044 return JERRY_TYPE_SYMBOL;
1045 }
1046#endif /* ENABLED (JERRY_ESNEXT) */
1047 case LIT_MAGIC_STRING_FUNCTION:
1048 {
1049 return JERRY_TYPE_FUNCTION;
1050 }
1051#if ENABLED (JERRY_BUILTIN_BIGINT)
1052 case LIT_MAGIC_STRING_BIGINT:
1053 {
1054 return JERRY_TYPE_BIGINT;
1055 }
1056#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
1057 default:
1058 {
1059 JERRY_ASSERT (lit_id == LIT_MAGIC_STRING_OBJECT);
1060
1061 /* Based on the ECMA 262 5.1 standard the 'null' value is an object.
1062 * Thus we'll do an extra check for 'null' here.
1063 */
1064 return ecma_is_value_null (value) ? JERRY_TYPE_NULL : JERRY_TYPE_OBJECT;
1065 }
1066 }
1067} /* jerry_value_get_type */
1068
1069/**
1070 * Get the object type of the given value
1071 *
1072 * @return JERRY_OBJECT_TYPE_NONE - if the given value is not an object
1073 * jerry_object_type_t value - otherwise
1074 */
1075jerry_object_type_t
1076jerry_object_get_type (const jerry_value_t value) /**< input value to check */
1077{
1078 jerry_assert_api_available ();
1079
1080 if (!ecma_is_value_object (value))
1081 {
1082 return JERRY_OBJECT_TYPE_NONE;
1083 }
1084
1085 ecma_object_t *obj_p = ecma_get_object_from_value (value);
1086 ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
1087
1088 switch (ecma_get_object_type (obj_p))
1089 {
1090 case ECMA_OBJECT_TYPE_FUNCTION:
1091 case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
1092 case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
1093 {
1094 return JERRY_OBJECT_TYPE_FUNCTION;
1095 }
1096 case ECMA_OBJECT_TYPE_ARRAY:
1097 {
1098 return JERRY_OBJECT_TYPE_ARRAY;
1099 }
1100#if ENABLED (JERRY_ESNEXT)
1101 case ECMA_OBJECT_TYPE_PROXY:
1102 {
1103 return JERRY_OBJECT_TYPE_PROXY;
1104 }
1105#endif /* ENABLED (JERRY_ESNEXT) */
1106 case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
1107 {
1108 switch (ext_obj_p->u.pseudo_array.type)
1109 {
1110 case ECMA_PSEUDO_ARRAY_ARGUMENTS:
1111 {
1112 return JERRY_OBJECT_TYPE_ARGUMENTS;
1113 }
1114#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
1115 case ECMA_PSEUDO_ARRAY_TYPEDARRAY:
1116 case ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO:
1117 {
1118 return JERRY_OBJECT_TYPE_TYPEDARRAY;
1119 }
1120#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
1121#if ENABLED (JERRY_ESNEXT)
1122 case ECMA_PSEUDO_STRING_ITERATOR:
1123 case ECMA_PSEUDO_ARRAY_ITERATOR:
1124#if ENABLED (JERRY_BUILTIN_MAP)
1125 case ECMA_PSEUDO_MAP_ITERATOR:
1126#endif /* ENABLED (JERRY_BUILTIN_MAP) */
1127#if ENABLED (JERRY_BUILTIN_SET)
1128 case ECMA_PSEUDO_SET_ITERATOR:
1129#endif /* ENABLED (JERRY_BUILTIN_SET) */
1130 {
1131 return JERRY_OBJECT_TYPE_ITERATOR;
1132 }
1133#endif /* ENABLED (JERRY_ESNEXT) */
1134 }
1135 break;
1136 }
1137 case ECMA_OBJECT_TYPE_CLASS:
1138 {
1139 switch (ext_obj_p->u.class_prop.class_id)
1140 {
1141 case LIT_MAGIC_STRING_ARGUMENTS_UL:
1142 {
1143 return JERRY_OBJECT_TYPE_ARGUMENTS;
1144 }
1145 case LIT_MAGIC_STRING_BOOLEAN_UL:
1146 {
1147 return JERRY_OBJECT_TYPE_BOOLEAN;
1148 }
1149 case LIT_MAGIC_STRING_DATE_UL:
1150 {
1151 return JERRY_OBJECT_TYPE_DATE;
1152 }
1153 case LIT_MAGIC_STRING_NUMBER_UL:
1154 {
1155 return JERRY_OBJECT_TYPE_NUMBER;
1156 }
1157 case LIT_MAGIC_STRING_REGEXP_UL:
1158 {
1159 return JERRY_OBJECT_TYPE_REGEXP;
1160 }
1161 case LIT_MAGIC_STRING_STRING_UL:
1162 {
1163 return JERRY_OBJECT_TYPE_STRING;
1164 }
1165#if ENABLED (JERRY_ESNEXT)
1166 case LIT_MAGIC_STRING_SYMBOL_UL:
1167 {
1168 return JERRY_OBJECT_TYPE_SYMBOL;
1169 }
1170 case LIT_MAGIC_STRING_GENERATOR_UL:
1171 {
1172 return JERRY_OBJECT_TYPE_GENERATOR;
1173 }
1174#endif /* ENABLED (JERRY_ESNEXT) */
1175#if ENABLED (JERRY_BUILTIN_BIGINT)
1176 case LIT_MAGIC_STRING_BIGINT_UL:
1177 {
1178 return JERRY_OBJECT_TYPE_BIGINT;
1179 }
1180#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
1181#if ENABLED (JERRY_BUILTIN_CONTAINER)
1182#if ENABLED (JERRY_BUILTIN_MAP)
1183 case LIT_MAGIC_STRING_MAP_UL:
1184#endif /* ENABLED (JERRY_BUILTIN_MAP) */
1185#if ENABLED (JERRY_BUILTIN_SET)
1186 case LIT_MAGIC_STRING_SET_UL:
1187#endif /* ENABLED (JERRY_BUILTIN_SET) */
1188#if ENABLED (JERRY_BUILTIN_WEAKMAP)
1189 case LIT_MAGIC_STRING_WEAKMAP_UL:
1190#endif /* ENABLED (JERRY_BUILTIN_WEAKMAP) */
1191#if ENABLED (JERRY_BUILTIN_WEAKSET)
1192 case LIT_MAGIC_STRING_WEAKSET_UL:
1193#endif /* ENABLED (JERRY_BUILTIN_WEAKSET) */
1194 {
1195 return JERRY_OBJECT_TYPE_CONTAINER;
1196 }
1197#endif /* ENABLED (JERRY_BUILTIN_CONTAINER) */
1198 default:
1199 {
1200 break;
1201 }
1202 }
1203 break;
1204 }
1205 default:
1206 {
1207 break;
1208 }
1209 }
1210
1211 return JERRY_OBJECT_TYPE_GENERIC;
1212} /* jerry_object_get_type */
1213
1214/**
1215 * Get the function type of the given value
1216 *
1217 * @return JERRY_FUNCTION_TYPE_NONE - if the given value is not a function object
1218 * jerry_function_type_t value - otherwise
1219 */
1220jerry_function_type_t
1221jerry_function_get_type (const jerry_value_t value) /**< input value to check */
1222{
1223 jerry_assert_api_available ();
1224
1225 if (ecma_is_value_object (value))
1226 {
1227 ecma_object_t *obj_p = ecma_get_object_from_value (value);
1228 ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
1229
1230 switch (ecma_get_object_type (obj_p))
1231 {
1232 case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
1233 {
1234 return JERRY_FUNCTION_TYPE_BOUND;
1235 }
1236 case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
1237 {
1238 return JERRY_FUNCTION_TYPE_GENERIC;
1239 }
1240 case ECMA_OBJECT_TYPE_FUNCTION:
1241 {
1242 if (!ecma_get_object_is_builtin (obj_p))
1243 {
1244 const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_obj_p);
1245
1246 switch (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags))
1247 {
1248#if ENABLED (JERRY_ESNEXT)
1249 case CBC_FUNCTION_ARROW:
1250 case CBC_FUNCTION_ASYNC_ARROW:
1251 {
1252 return JERRY_FUNCTION_TYPE_ARROW;
1253 }
1254 case CBC_FUNCTION_GENERATOR:
1255 case CBC_FUNCTION_ASYNC_GENERATOR:
1256 {
1257 return JERRY_FUNCTION_TYPE_GENERATOR;
1258 }
1259#endif /* ENABLED (JERRY_ESNEXT) */
1260 case CBC_FUNCTION_ACCESSOR:
1261 {
1262 return JERRY_FUNCTION_TYPE_ACCESSOR;
1263 }
1264 default:
1265 {
1266 break;
1267 }
1268 }
1269 }
1270 return JERRY_FUNCTION_TYPE_GENERIC;
1271 }
1272 default:
1273 {
1274 break;
1275 }
1276 }
1277 }
1278
1279 return JERRY_FUNCTION_TYPE_NONE;
1280} /* jerry_function_get_type */
1281
1282/**
1283 * Get the itearator type of the given value
1284 *
1285 * @return JERRY_ITERATOR_TYPE_NONE - if the given value is not an iterator object
1286 * jerry_iterator_type_t value - otherwise
1287 */
1288jerry_iterator_type_t
1289jerry_iterator_get_type (const jerry_value_t value) /**< input value to check */
1290{
1291 jerry_assert_api_available ();
1292
1293#if ENABLED (JERRY_ESNEXT)
1294 if (ecma_is_value_object (value))
1295 {
1296 ecma_object_t *obj_p = ecma_get_object_from_value (value);
1297 ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
1298
1299 if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY)
1300 {
1301 switch (ext_obj_p->u.pseudo_array.type)
1302 {
1303 case ECMA_PSEUDO_ARRAY_ITERATOR:
1304 {
1305 return JERRY_ITERATOR_TYPE_ARRAY;
1306 }
1307 case ECMA_PSEUDO_STRING_ITERATOR:
1308 {
1309 return JERRY_ITERATOR_TYPE_STRING;
1310 }
1311#if ENABLED (JERRY_BUILTIN_MAP)
1312 case ECMA_PSEUDO_MAP_ITERATOR:
1313 {
1314 return JERRY_ITERATOR_TYPE_MAP;
1315 }
1316#endif /* ENABLED (JERRY_BUILTIN_MAP) */
1317#if ENABLED (JERRY_BUILTIN_SET)
1318 case ECMA_PSEUDO_SET_ITERATOR:
1319 {
1320 return JERRY_ITERATOR_TYPE_SET;
1321 }
1322#endif /* ENABLED (JERRY_BUILTIN_SET) */
1323 default:
1324 {
1325 break;
1326 }
1327 }
1328 }
1329 }
1330#else /* !ENABLED (JERRY_ESNEXT) */
1331 JERRY_UNUSED (value);
1332#endif /* ENABLED (JERRY_ESNEXT) */
1333
1334 return JERRY_ITERATOR_TYPE_NONE;
1335} /* jerry_iterator_get_type */
1336
1337/**
1338 * Check if the specified feature is enabled.
1339 *
1340 * @return true - if the specified feature is enabled,
1341 * false - otherwise
1342 */
1343bool
1344jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check */
1345{
1346 JERRY_ASSERT (feature < JERRY_FEATURE__COUNT);
1347
1348 return (false
1349#if ENABLED (JERRY_CPOINTER_32_BIT)
1350 || feature == JERRY_FEATURE_CPOINTER_32_BIT
1351#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
1352#if ENABLED (JERRY_ERROR_MESSAGES)
1353 || feature == JERRY_FEATURE_ERROR_MESSAGES
1354#endif /* ENABLED (JERRY_ERROR_MESSAGES) */
1355#if ENABLED (JERRY_PARSER)
1356 || feature == JERRY_FEATURE_JS_PARSER
1357#endif /* ENABLED (JERRY_PARSER) */
1358#if ENABLED (JERRY_MEM_STATS)
1359 || feature == JERRY_FEATURE_MEM_STATS
1360#endif /* ENABLED (JERRY_MEM_STATS) */
1361#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
1362 || feature == JERRY_FEATURE_PARSER_DUMP
1363#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
1364#if ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE)
1365 || feature == JERRY_FEATURE_REGEXP_DUMP
1366#endif /* ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE) */
1367#if ENABLED (JERRY_SNAPSHOT_SAVE)
1368 || feature == JERRY_FEATURE_SNAPSHOT_SAVE
1369#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
1370#if ENABLED (JERRY_SNAPSHOT_EXEC)
1371 || feature == JERRY_FEATURE_SNAPSHOT_EXEC
1372#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
1373#if ENABLED (JERRY_DEBUGGER)
1374 || feature == JERRY_FEATURE_DEBUGGER
1375#endif /* ENABLED (JERRY_DEBUGGER) */
1376#if ENABLED (JERRY_VM_EXEC_STOP)
1377 || feature == JERRY_FEATURE_VM_EXEC_STOP
1378#endif /* ENABLED (JERRY_VM_EXEC_STOP) */
1379#if ENABLED (JERRY_BUILTIN_JSON)
1380 || feature == JERRY_FEATURE_JSON
1381#endif /* ENABLED (JERRY_BUILTIN_JSON) */
1382#if ENABLED (JERRY_BUILTIN_PROMISE)
1383 || feature == JERRY_FEATURE_PROMISE
1384#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
1385#if ENABLED (JERRY_ESNEXT)
1386 || feature == JERRY_FEATURE_SYMBOL
1387#endif /* ENABLED (JERRY_ESNEXT) */
1388#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
1389 || feature == JERRY_FEATURE_TYPEDARRAY
1390#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
1391#if ENABLED (JERRY_BUILTIN_DATAVIEW)
1392 || feature == JERRY_FEATURE_DATAVIEW
1393#endif /* ENABLED (JERRY_BUILTIN_DATAVIEW) */
1394#if ENABLED (JERRY_BUILTIN_PROXY)
1395 || feature == JERRY_FEATURE_PROXY
1396#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
1397#if ENABLED (JERRY_BUILTIN_DATE)
1398 || feature == JERRY_FEATURE_DATE
1399#endif /* ENABLED (JERRY_BUILTIN_DATE) */
1400#if ENABLED (JERRY_BUILTIN_REGEXP)
1401 || feature == JERRY_FEATURE_REGEXP
1402#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
1403#if ENABLED (JERRY_LINE_INFO)
1404 || feature == JERRY_FEATURE_LINE_INFO
1405#endif /* ENABLED (JERRY_LINE_INFO) */
1406#if ENABLED (JERRY_LOGGING)
1407 || feature == JERRY_FEATURE_LOGGING
1408#endif /* ENABLED (JERRY_LOGGING) */
1409#if ENABLED (JERRY_BUILTIN_MAP)
1410 || feature == JERRY_FEATURE_MAP
1411#endif /* ENABLED (JERRY_BUILTIN_MAP) */
1412#if ENABLED (JERRY_BUILTIN_SET)
1413 || feature == JERRY_FEATURE_SET
1414#endif /* ENABLED (JERRY_BUILTIN_SET) */
1415#if ENABLED (JERRY_BUILTIN_WEAKMAP)
1416 || feature == JERRY_FEATURE_WEAKMAP
1417#endif /* ENABLED (JERRY_BUILTIN_WEAKMAP) */
1418#if ENABLED (JERRY_BUILTIN_WEAKSET)
1419 || feature == JERRY_FEATURE_WEAKSET
1420#endif /* ENABLED (JERRY_BUILTIN_WEAKSET) */
1421#if ENABLED (JERRY_BUILTIN_BIGINT)
1422 || feature == JERRY_FEATURE_BIGINT
1423#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
1424#if ENABLED (JERRY_BUILTIN_REALMS)
1425 || feature == JERRY_FEATURE_REALM
1426#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
1427 );
1428} /* jerry_is_feature_enabled */
1429
1430/**
1431 * Perform binary operation on the given operands (==, ===, <, >, etc.).
1432 *
1433 * @return error - if argument has an error flag or operation is unsuccessful or unsupported
1434 * true/false - the result of the binary operation on the given operands otherwise
1435 */
1436jerry_value_t
1437jerry_binary_operation (jerry_binary_operation_t op, /**< operation */
1438 const jerry_value_t lhs, /**< first operand */
1439 const jerry_value_t rhs) /**< second operand */
1440{
1441 jerry_assert_api_available ();
1442
1443 if (ecma_is_value_error_reference (lhs) || ecma_is_value_error_reference (rhs))
1444 {
1445 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1446 }
1447
1448 switch (op)
1449 {
1450 case JERRY_BIN_OP_EQUAL:
1451 {
1452 return jerry_return (ecma_op_abstract_equality_compare (lhs, rhs));
1453 }
1454 case JERRY_BIN_OP_STRICT_EQUAL:
1455 {
1456 return ecma_make_boolean_value (ecma_op_strict_equality_compare (lhs, rhs));
1457 }
1458 case JERRY_BIN_OP_LESS:
1459 {
1460 return jerry_return (opfunc_relation (lhs, rhs, true, false));
1461 }
1462 case JERRY_BIN_OP_LESS_EQUAL:
1463 {
1464 return jerry_return (opfunc_relation (lhs, rhs, false, true));
1465 }
1466 case JERRY_BIN_OP_GREATER:
1467 {
1468 return jerry_return (opfunc_relation (lhs, rhs, false, false));
1469 }
1470 case JERRY_BIN_OP_GREATER_EQUAL:
1471 {
1472 return jerry_return (opfunc_relation (lhs, rhs, true, true));
1473 }
1474 case JERRY_BIN_OP_INSTANCEOF:
1475 {
1476 if (!ecma_is_value_object (lhs)
1477 || !ecma_op_is_callable (rhs))
1478 {
1479 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
1480 }
1481
1482 ecma_object_t *proto_obj_p = ecma_get_object_from_value (rhs);
1483 return jerry_return (ecma_op_object_has_instance (proto_obj_p, lhs));
1484 }
1485 case JERRY_BIN_OP_ADD:
1486 {
1487 return jerry_return (opfunc_addition (lhs, rhs));
1488 }
1489 case JERRY_BIN_OP_SUB:
1490 case JERRY_BIN_OP_MUL:
1491 case JERRY_BIN_OP_DIV:
1492 case JERRY_BIN_OP_REM:
1493 {
1494 return jerry_return (do_number_arithmetic (op - ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET, lhs, rhs));
1495 }
1496 default:
1497 {
1498 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Unsupported binary operation")));
1499 }
1500 }
1501} /* jerry_binary_operation */
1502
1503/**
1504 * Create abort from an api value.
1505 *
1506 * Create abort value from an api value. If the second argument is true
1507 * it will release the input api value.
1508 *
1509 * @return api abort value
1510 */
1511jerry_value_t
1512jerry_create_abort_from_value (jerry_value_t value, /**< api value */
1513 bool release) /**< release api value */
1514{
1515 jerry_assert_api_available ();
1516
1517 if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1518 {
1519 /* This is a rare case so it is optimized for
1520 * binary size rather than performance. */
1521 if (jerry_value_is_abort (value))
1522 {
1523 return release ? value : jerry_acquire_value (value);
1524 }
1525
1526 value = jerry_get_value_from_error (value, release);
1527 release = true;
1528 }
1529
1530 if (!release)
1531 {
1532 value = ecma_copy_value (value);
1533 }
1534
1535 return ecma_create_error_reference (value, false);
1536} /* jerry_create_abort_from_value */
1537
1538/**
1539 * Create error from an api value.
1540 *
1541 * Create error value from an api value. If the second argument is true
1542 * it will release the input api value.
1543 *
1544 * @return api error value
1545 */
1546jerry_value_t
1547jerry_create_error_from_value (jerry_value_t value, /**< api value */
1548 bool release) /**< release api value */
1549{
1550 jerry_assert_api_available ();
1551
1552 if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1553 {
1554 /* This is a rare case so it is optimized for
1555 * binary size rather than performance. */
1556 if (!jerry_value_is_abort (value))
1557 {
1558 return release ? value : jerry_acquire_value (value);
1559 }
1560
1561 value = jerry_get_value_from_error (value, release);
1562 release = true;
1563 }
1564
1565 if (!release)
1566 {
1567 value = ecma_copy_value (value);
1568 }
1569
1570 return ecma_create_error_reference (value, true);
1571} /* jerry_create_error_from_value */
1572
1573/**
1574 * Get the value from an error value.
1575 *
1576 * Extract the api value from an error. If the second argument is true
1577 * it will release the input error value.
1578 *
1579 * Note:
1580 * returned value must be freed with jerry_release_value, when it is no longer needed.
1581 *
1582 * @return jerry_value_t value
1583 */
1584jerry_value_t
1585jerry_get_value_from_error (jerry_value_t value, /**< api value */
1586 bool release) /**< release api value */
1587{
1588 jerry_assert_api_available ();
1589
1590 if (!ecma_is_value_error_reference (value))
1591 {
1592 return release ? value : ecma_copy_value (value);
1593 }
1594
1595 jerry_value_t ret_val = jerry_acquire_value (ecma_get_extended_primitive_from_value (value)->u.value);
1596
1597 if (release)
1598 {
1599 jerry_release_value (value);
1600 }
1601 return ret_val;
1602} /* jerry_get_value_from_error */
1603
1604/**
1605 * Set new decorator callback for Error objects. The decorator can
1606 * create or update any properties of the newly created Error object.
1607 */
1608void
1609jerry_set_error_object_created_callback (jerry_error_object_created_callback_t callback, /**< new callback */
1610 void *user_p) /**< user pointer passed to the callback */
1611{
1612 jerry_assert_api_available ();
1613
1614 JERRY_CONTEXT (error_object_created_callback_p) = callback;
1615 JERRY_CONTEXT (error_object_created_callback_user_p) = user_p;
1616} /* jerry_set_error_object_created_callback */
1617
1618/**
1619 * Return the type of the Error object if possible.
1620 *
1621 * @return one of the jerry_error_t value as the type of the Error object
1622 * JERRY_ERROR_NONE - if the input value is not an Error object
1623 */
1624jerry_error_t
1625jerry_get_error_type (jerry_value_t value) /**< api value */
1626{
1627 if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1628 {
1629 value = ecma_get_extended_primitive_from_value (value)->u.value;
1630 }
1631
1632 if (!ecma_is_value_object (value))
1633 {
1634 return JERRY_ERROR_NONE;
1635 }
1636
1637 ecma_object_t *object_p = ecma_get_object_from_value (value);
1638 ecma_standard_error_t error_type = ecma_get_error_type (object_p);
1639
1640 return (jerry_error_t) error_type;
1641} /* jerry_get_error_type */
1642
1643/**
1644 * Get boolean from the specified value.
1645 *
1646 * @return true or false.
1647 */
1648bool
1649jerry_get_boolean_value (const jerry_value_t value) /**< api value */
1650{
1651 jerry_assert_api_available ();
1652
1653 return ecma_is_value_true (value);
1654} /* jerry_get_boolean_value */
1655
1656/**
1657 * Get number from the specified value as a double.
1658 *
1659 * @return stored number as double
1660 */
1661double
1662jerry_get_number_value (const jerry_value_t value) /**< api value */
1663{
1664 jerry_assert_api_available ();
1665
1666 if (!ecma_is_value_number (value))
1667 {
1668 return 0;
1669 }
1670
1671 return (double) ecma_get_number_from_value (value);
1672} /* jerry_get_number_value */
1673
1674/**
1675 * Call ToBoolean operation on the api value.
1676 *
1677 * @return true - if the logical value is true
1678 * false - otherwise
1679 */
1680bool
1681jerry_value_to_boolean (const jerry_value_t value) /**< input value */
1682{
1683 jerry_assert_api_available ();
1684
1685 if (ecma_is_value_error_reference (value))
1686 {
1687 return false;
1688 }
1689
1690 return ecma_op_to_boolean (value);
1691} /* jerry_value_to_boolean */
1692
1693/**
1694 * Call ToNumber operation on the api value.
1695 *
1696 * Note:
1697 * returned value must be freed with jerry_release_value, when it is no longer needed.
1698 *
1699 * @return converted number value - if success
1700 * thrown error - otherwise
1701 */
1702jerry_value_t
1703jerry_value_to_number (const jerry_value_t value) /**< input value */
1704{
1705 jerry_assert_api_available ();
1706
1707 if (ecma_is_value_error_reference (value))
1708 {
1709 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1710 }
1711
1712 ecma_number_t num;
1713 ecma_value_t ret_value = ecma_op_to_number (value, &num);
1714
1715 if (ECMA_IS_VALUE_ERROR (ret_value))
1716 {
1717 return ecma_create_error_reference_from_context ();
1718 }
1719
1720 return ecma_make_number_value (num);
1721} /* jerry_value_to_number */
1722
1723/**
1724 * Call ToObject operation on the api value.
1725 *
1726 * Note:
1727 * returned value must be freed with jerry_release_value, when it is no longer needed.
1728 *
1729 * @return converted object value - if success
1730 * thrown error - otherwise
1731 */
1732jerry_value_t
1733jerry_value_to_object (const jerry_value_t value) /**< input value */
1734{
1735 jerry_assert_api_available ();
1736
1737 if (ecma_is_value_error_reference (value))
1738 {
1739 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1740 }
1741
1742 return jerry_return (ecma_op_to_object (value));
1743} /* jerry_value_to_object */
1744
1745/**
1746 * Call ToPrimitive operation on the api value.
1747 *
1748 * Note:
1749 * returned value must be freed with jerry_release_value, when it is no longer needed.
1750 *
1751 * @return converted primitive value - if success
1752 * thrown error - otherwise
1753 */
1754jerry_value_t
1755jerry_value_to_primitive (const jerry_value_t value) /**< input value */
1756{
1757 jerry_assert_api_available ();
1758
1759 if (ecma_is_value_error_reference (value))
1760 {
1761 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1762 }
1763
1764 return jerry_return (ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NO));
1765} /* jerry_value_to_primitive */
1766
1767/**
1768 * Call the ToString ecma builtin operation on the api value.
1769 *
1770 * Note:
1771 * returned value must be freed with jerry_release_value, when it is no longer needed.
1772 *
1773 * @return converted string value - if success
1774 * thrown error - otherwise
1775 */
1776jerry_value_t
1777jerry_value_to_string (const jerry_value_t value) /**< input value */
1778{
1779
1780 jerry_assert_api_available ();
1781
1782 if (ecma_is_value_error_reference (value))
1783 {
1784 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1785 }
1786
1787 ecma_string_t *str_p = ecma_op_to_string (value);
1788 if (JERRY_UNLIKELY (str_p == NULL))
1789 {
1790 return ecma_create_error_reference_from_context ();
1791 }
1792
1793 return ecma_make_string_value (str_p);
1794} /* jerry_value_to_string */
1795
1796/**
1797 * Call the BigInt constructor ecma builtin operation on the api value.
1798 *
1799 * Note:
1800 * returned value must be freed with jerry_release_value, when it is no longer needed.
1801 *
1802 * @return BigInt value - if success
1803 * thrown error - otherwise
1804 */
1805jerry_value_t
1806jerry_value_to_bigint (const jerry_value_t value) /**< input value */
1807{
1808 jerry_assert_api_available ();
1809
1810#if ENABLED (JERRY_BUILTIN_BIGINT)
1811 if (ecma_is_value_error_reference (value))
1812 {
1813 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1814 }
1815
1816 return jerry_return (ecma_bigint_to_bigint (value, true));
1817#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
1818 JERRY_UNUSED (value);
1819 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_bigint_not_supported_p)));
1820#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
1821} /* jerry_value_to_bigint */
1822
1823/**
1824 * Convert any number to integer number.
1825 *
1826 * Note:
1827 * For non-number values 0 is returned.
1828 *
1829 * @return integer representation of the number.
1830 */
1831double
1832jerry_value_as_integer (const jerry_value_t value) /**< input value */
1833{
1834 jerry_assert_api_available ();
1835
1836 if (!ecma_is_value_number (value))
1837 {
1838 return 0;
1839 }
1840
1841 double number = ecma_get_number_from_value (value);
1842
1843 if (ecma_number_is_nan (number))
1844 {
1845 return ECMA_NUMBER_ZERO;
1846 }
1847
1848 if (ecma_number_is_zero (number) || ecma_number_is_infinity (number))
1849 {
1850 return number;
1851 }
1852
1853 ecma_number_t floor_fabs = (ecma_number_t) floor (fabs (number));
1854
1855 return ecma_number_is_negative (number) ? -floor_fabs : floor_fabs;
1856} /* jerry_value_as_integer */
1857
1858/**
1859 * Convert any number to int32 number.
1860 *
1861 * Note:
1862 * For non-number values 0 is returned.
1863 *
1864 * @return int32 representation of the number.
1865 */
1866int32_t
1867jerry_value_as_int32 (const jerry_value_t value) /**< input value */
1868{
1869 jerry_assert_api_available ();
1870
1871 if (!ecma_is_value_number (value))
1872 {
1873 return 0;
1874 }
1875
1876 return ecma_number_to_int32 (ecma_get_number_from_value (value));
1877} /* jerry_value_as_int32 */
1878
1879/**
1880 * Convert any number to uint32 number.
1881 *
1882 * Note:
1883 * For non-number values 0 is returned.
1884 *
1885 * @return uint32 representation of the number.
1886 */
1887uint32_t
1888jerry_value_as_uint32 (const jerry_value_t value) /**< input value */
1889{
1890 jerry_assert_api_available ();
1891
1892 if (!ecma_is_value_number (value))
1893 {
1894 return 0;
1895 }
1896
1897 return ecma_number_to_uint32 (ecma_get_number_from_value (value));
1898} /* jerry_value_as_uint32 */
1899
1900/**
1901 * Acquire specified Jerry API value.
1902 *
1903 * Note:
1904 * returned value must be freed with jerry_release_value, when it is no longer needed.
1905 *
1906 * @return acquired api value
1907 */
1908jerry_value_t
1909jerry_acquire_value (jerry_value_t value) /**< API value */
1910{
1911 jerry_assert_api_available ();
1912
1913 if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1914 {
1915 ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value));
1916 return value;
1917 }
1918
1919 return ecma_copy_value (value);
1920} /* jerry_acquire_value */
1921
1922/**
1923 * Release specified Jerry API value
1924 */
1925void
1926jerry_release_value (jerry_value_t value) /**< API value */
1927{
1928 jerry_assert_api_available ();
1929
1930 if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1931 {
1932 ecma_deref_error_reference (ecma_get_extended_primitive_from_value (value));
1933 return;
1934 }
1935
1936 ecma_free_value (value);
1937} /* jerry_release_value */
1938
1939/**
1940 * Create an array object value
1941 *
1942 * Note:
1943 * returned value must be freed with jerry_release_value, when it is no longer needed.
1944 *
1945 * @return value of the constructed array object
1946 */
1947jerry_value_t
1948jerry_create_array (uint32_t size) /**< size of array */
1949{
1950 jerry_assert_api_available ();
1951
1952 ecma_object_t *array_p = ecma_op_new_array_object (size);
1953 return ecma_make_object_value (array_p);
1954} /* jerry_create_array */
1955
1956/**
1957 * Create a jerry_value_t representing a boolean value from the given boolean parameter.
1958 *
1959 * @return value of the created boolean
1960 */
1961jerry_value_t
1962jerry_create_boolean (bool value) /**< bool value from which a jerry_value_t will be created */
1963{
1964 jerry_assert_api_available ();
1965
1966 return jerry_return (ecma_make_boolean_value (value));
1967} /* jerry_create_boolean */
1968
1969/**
1970 * Create an error object
1971 *
1972 * Note:
1973 * - returned value must be freed with jerry_release_value, when it is no longer needed
1974 * - the error flag is set for the returned value
1975 *
1976 * @return value of the constructed error object
1977 */
1978jerry_value_t
1979jerry_create_error (jerry_error_t error_type, /**< type of error */
1980 const jerry_char_t *message_p) /**< value of 'message' property
1981 * of constructed error object */
1982{
1983 return jerry_create_error_sz (error_type,
1984 (lit_utf8_byte_t *) message_p,
1985 lit_zt_utf8_string_size (message_p));
1986} /* jerry_create_error */
1987
1988/**
1989 * Create an error object
1990 *
1991 * Note:
1992 * - returned value must be freed with jerry_release_value, when it is no longer needed
1993 * - the error flag is set for the returned value
1994 *
1995 * @return value of the constructed error object
1996 */
1997jerry_value_t
1998jerry_create_error_sz (jerry_error_t error_type, /**< type of error */
1999 const jerry_char_t *message_p, /**< value of 'message' property
2000 * of constructed error object */
2001 jerry_size_t message_size) /**< size of the message in bytes */
2002{
2003 jerry_assert_api_available ();
2004
2005 if (message_p == NULL || message_size == 0)
2006 {
2007 return ecma_create_error_object_reference (ecma_new_standard_error ((ecma_standard_error_t) error_type, NULL));
2008 }
2009 else
2010 {
2011 ecma_string_t *message_string_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) message_p,
2012 (lit_utf8_size_t) message_size);
2013
2014 ecma_object_t *error_object_p = ecma_new_standard_error ((ecma_standard_error_t) error_type,
2015 message_string_p);
2016
2017 ecma_deref_ecma_string (message_string_p);
2018
2019 return ecma_create_error_object_reference (error_object_p);
2020 }
2021} /* jerry_create_error_sz */
2022
2023/**
2024 * Create an external function object
2025 *
2026 * Note:
2027 * returned value must be freed with jerry_release_value, when it is no longer needed.
2028 *
2029 * @return value of the constructed function object
2030 */
2031jerry_value_t
2032jerry_create_external_function (jerry_external_handler_t handler_p) /**< pointer to native handler
2033 * for the function */
2034{
2035 jerry_assert_api_available ();
2036
2037 ecma_object_t *func_obj_p = ecma_op_create_external_function_object (handler_p);
2038 return ecma_make_object_value (func_obj_p);
2039} /* jerry_create_external_function */
2040
2041/**
2042 * Creates a jerry_value_t representing a number value.
2043 *
2044 * Note:
2045 * returned value must be freed with jerry_release_value, when it is no longer needed.
2046 *
2047 * @return jerry_value_t created from the given double argument.
2048 */
2049jerry_value_t
2050jerry_create_number (double value) /**< double value from which a jerry_value_t will be created */
2051{
2052 jerry_assert_api_available ();
2053
2054 return ecma_make_number_value ((ecma_number_t) value);
2055} /* jerry_create_number */
2056
2057/**
2058 * Creates a jerry_value_t representing a positive or negative infinity value.
2059 *
2060 * Note:
2061 * returned value must be freed with jerry_release_value, when it is no longer needed.
2062 *
2063 * @return jerry_value_t representing an infinity value.
2064 */
2065jerry_value_t
2066jerry_create_number_infinity (bool sign) /**< true for negative Infinity
2067 * false for positive Infinity */
2068{
2069 jerry_assert_api_available ();
2070
2071 return ecma_make_number_value (ecma_number_make_infinity (sign));
2072} /* jerry_create_number_infinity */
2073
2074/**
2075 * Creates a jerry_value_t representing a not-a-number value.
2076 *
2077 * Note:
2078 * returned value must be freed with jerry_release_value, when it is no longer needed.
2079 *
2080 * @return jerry_value_t representing a not-a-number value.
2081 */
2082jerry_value_t
2083jerry_create_number_nan (void)
2084{
2085 jerry_assert_api_available ();
2086
2087 return ecma_make_nan_value ();
2088} /* jerry_create_number_nan */
2089
2090/**
2091 * Creates a jerry_value_t representing an undefined value.
2092 *
2093 * @return value of undefined
2094 */
2095jerry_value_t
2096jerry_create_undefined (void)
2097{
2098 jerry_assert_api_available ();
2099
2100 return ECMA_VALUE_UNDEFINED;
2101} /* jerry_create_undefined */
2102
2103/**
2104 * Creates and returns a jerry_value_t with type null object.
2105 *
2106 * @return jerry_value_t representing null
2107 */
2108jerry_value_t
2109jerry_create_null (void)
2110{
2111 jerry_assert_api_available ();
2112
2113 return ECMA_VALUE_NULL;
2114} /* jerry_create_null */
2115
2116/**
2117 * Create new JavaScript object, like with new Object().
2118 *
2119 * Note:
2120 * returned value must be freed with jerry_release_value, when it is no longer needed.
2121 *
2122 * @return value of the created object
2123 */
2124jerry_value_t
2125jerry_create_object (void)
2126{
2127 jerry_assert_api_available ();
2128
2129 return ecma_make_object_value (ecma_op_create_object_object_noarg ());
2130} /* jerry_create_object */
2131
2132/**
2133 * Create an empty Promise object which can be resolve/reject later
2134 * by calling jerry_resolve_or_reject_promise.
2135 *
2136 * Note:
2137 * returned value must be freed with jerry_release_value, when it is no longer needed.
2138 *
2139 * @return value of the created object
2140 */
2141jerry_value_t
2142jerry_create_promise (void)
2143{
2144 jerry_assert_api_available ();
2145
2146#if ENABLED (JERRY_BUILTIN_PROMISE)
2147 ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p);
2148
2149 if (old_new_target_p == NULL)
2150 {
2151 JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE);
2152 }
2153
2154 ecma_value_t promise_value = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_PROMISE_EXECUTOR_EMPTY);
2155
2156 JERRY_CONTEXT (current_new_target_p) = old_new_target_p;
2157 return promise_value;
2158#else /* !ENABLED (JERRY_BUILTIN_PROMISE) */
2159 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
2160#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
2161} /* jerry_create_promise */
2162
2163/**
2164 * Create a new Proxy object with the given target and handler
2165 *
2166 * Note:
2167 * returned value must be freed with jerry_release_value, when it is no longer needed.
2168 *
2169 * @return value of the created Proxy object
2170 */
2171jerry_value_t
2172jerry_create_proxy (const jerry_value_t target, /**< target argument */
2173 const jerry_value_t handler) /**< handler argument */
2174{
2175 jerry_assert_api_available ();
2176
2177 if (ecma_is_value_error_reference (target)
2178 || ecma_is_value_error_reference (handler))
2179 {
2180 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2181 }
2182
2183#if ENABLED (JERRY_BUILTIN_PROXY)
2184 ecma_object_t *proxy_p = ecma_proxy_create (target, handler);
2185 return jerry_return (proxy_p == NULL ? ECMA_VALUE_ERROR : ecma_make_object_value (proxy_p));
2186#else /* !ENABLED (JERRY_BUILTIN_PROXY) */
2187 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Proxy is not supported.")));
2188#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
2189} /* jerry_create_proxy */
2190
2191/**
2192 * Create string from a valid UTF-8 string
2193 *
2194 * Note:
2195 * returned value must be freed with jerry_release_value when it is no longer needed.
2196 *
2197 * @return value of the created string
2198 */
2199jerry_value_t
2200jerry_create_string_from_utf8 (const jerry_char_t *str_p) /**< pointer to string */
2201{
2202 return jerry_create_string_sz_from_utf8 (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p));
2203} /* jerry_create_string_from_utf8 */
2204
2205/**
2206 * Create string from a valid UTF-8 string
2207 *
2208 * Note:
2209 * returned value must be freed with jerry_release_value when it is no longer needed.
2210 *
2211 * @return value of the created string
2212 */
2213jerry_value_t
2214jerry_create_string_sz_from_utf8 (const jerry_char_t *str_p, /**< pointer to string */
2215 jerry_size_t str_size) /**< string size */
2216{
2217 jerry_assert_api_available ();
2218
2219 ecma_string_t *ecma_str_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 ((lit_utf8_byte_t *) str_p,
2220 (lit_utf8_size_t) str_size);
2221
2222 return ecma_make_string_value (ecma_str_p);
2223} /* jerry_create_string_sz_from_utf8 */
2224
2225/**
2226 * Create string from a valid CESU-8 string
2227 *
2228 * Note:
2229 * returned value must be freed with jerry_release_value, when it is no longer needed.
2230 *
2231 * @return value of the created string
2232 */
2233jerry_value_t
2234jerry_create_string (const jerry_char_t *str_p) /**< pointer to string */
2235{
2236 return jerry_create_string_sz (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p));
2237} /* jerry_create_string */
2238
2239/**
2240 * Create string from a valid CESU-8 string
2241 *
2242 * Note:
2243 * returned value must be freed with jerry_release_value when it is no longer needed.
2244 *
2245 * @return value of the created string
2246 */
2247jerry_value_t
2248jerry_create_string_sz (const jerry_char_t *str_p, /**< pointer to string */
2249 jerry_size_t str_size) /**< string size */
2250{
2251 jerry_assert_api_available ();
2252
2253 ecma_string_t *ecma_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) str_p,
2254 (lit_utf8_size_t) str_size);
2255 return ecma_make_string_value (ecma_str_p);
2256} /* jerry_create_string_sz */
2257
2258/**
2259 * Create external string from a valid CESU-8 string
2260 *
2261 * Note:
2262 * returned value must be freed with jerry_release_value, when it is no longer needed.
2263 *
2264 * @return value of the created external string
2265 */
2266jerry_value_t
2267jerry_create_external_string (const jerry_char_t *str_p, /**< pointer to string */
2268 jerry_object_native_free_callback_t free_cb) /**< free callback */
2269{
2270 return jerry_create_external_string_sz (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p), free_cb);
2271} /* jerry_create_external_string */
2272
2273/**
2274 * Create external string from a valid CESU-8 string
2275 *
2276 * Note:
2277 * returned value must be freed with jerry_release_value when it is no longer needed.
2278 *
2279 * @return value of the created external string
2280 */
2281jerry_value_t
2282jerry_create_external_string_sz (const jerry_char_t *str_p, /**< pointer to string */
2283 jerry_size_t str_size, /**< string size */
2284 jerry_object_native_free_callback_t free_cb) /**< free callback */
2285{
2286 jerry_assert_api_available ();
2287
2288 ecma_string_t *ecma_str_p = ecma_new_ecma_external_string_from_cesu8 ((lit_utf8_byte_t *) str_p,
2289 (lit_utf8_size_t) str_size,
2290 free_cb);
2291 return ecma_make_string_value (ecma_str_p);
2292} /* jerry_create_external_string_sz */
2293
2294/**
2295 * Create symbol from an api value
2296 *
2297 * Note:
2298 * The given argument is converted to string. This operation can throw an error.
2299 * returned value must be freed with jerry_release_value when it is no longer needed.
2300 *
2301 * @return value of the created symbol, if success
2302 * thrown error, otherwise
2303 */
2304jerry_value_t
2305jerry_create_symbol (const jerry_value_t value) /**< api value */
2306{
2307 jerry_assert_api_available ();
2308
2309 if (ecma_is_value_error_reference (value))
2310 {
2311 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2312 }
2313
2314#if ENABLED (JERRY_ESNEXT)
2315 return jerry_return (ecma_op_create_symbol (&value, 1));
2316#else /* !ENABLED (JERRY_ESNEXT) */
2317 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported.")));
2318#endif /* ENABLED (JERRY_ESNEXT) */
2319} /* jerry_create_symbol */
2320
2321/**
2322 * Create BigInt from a sequence of uint64 digits
2323 *
2324 * @return value of the created bigint, if success
2325 * thrown error, otherwise
2326 */
2327jerry_value_t
2328jerry_create_bigint (const uint64_t *digits_p, /**< BigInt digits (lowest digit first) */
2329 uint32_t size, /**< number of BigInt digits */
2330 bool sign) /**< sign bit, true if the result should be negative */
2331{
2332 jerry_assert_api_available ();
2333
2334#if ENABLED (JERRY_BUILTIN_BIGINT)
2335 return jerry_return (ecma_bigint_create_from_digits (digits_p, size, sign));
2336#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
2337 JERRY_UNUSED (digits_p);
2338 JERRY_UNUSED (size);
2339 JERRY_UNUSED (sign);
2340 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_bigint_not_supported_p)));
2341#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
2342} /* jerry_create_bigint */
2343
2344/**
2345 * Calculates the size of the given pattern and creates a RegExp object.
2346 *
2347 * @return value of the constructed RegExp object.
2348 */
2349jerry_value_t
2350jerry_create_regexp (const jerry_char_t *pattern_p, /**< zero-terminated UTF-8 string as RegExp pattern */
2351 uint16_t flags) /**< optional RegExp flags */
2352{
2353 return jerry_create_regexp_sz (pattern_p, lit_zt_utf8_string_size (pattern_p), flags);
2354} /* jerry_create_regexp */
2355
2356/**
2357 * Creates a RegExp object with the given pattern and flags.
2358 *
2359 * @return value of the constructed RegExp object.
2360 */
2361jerry_value_t
2362jerry_create_regexp_sz (const jerry_char_t *pattern_p, /**< zero-terminated UTF-8 string as RegExp pattern */
2363 jerry_size_t pattern_size, /**< length of the pattern */
2364 uint16_t flags) /**< optional RegExp flags */
2365{
2366 jerry_assert_api_available ();
2367
2368#if ENABLED (JERRY_BUILTIN_REGEXP)
2369 if (!lit_is_valid_utf8_string (pattern_p, pattern_size))
2370 {
2371 return jerry_throw (ecma_raise_common_error (ECMA_ERR_MSG ("Input must be a valid utf8 string")));
2372 }
2373
2374 ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL);
2375
2376 if (JERRY_UNLIKELY (regexp_obj_p == NULL))
2377 {
2378 return ECMA_VALUE_ERROR;
2379 }
2380
2381 ecma_string_t *ecma_pattern = ecma_new_ecma_string_from_utf8 (pattern_p, pattern_size);
2382
2383 jerry_value_t ret_val = ecma_op_create_regexp_with_flags (regexp_obj_p,
2384 ecma_make_string_value (ecma_pattern),
2385 flags);
2386 ecma_deref_ecma_string (ecma_pattern);
2387
2388 return ret_val;
2389
2390#else /* !ENABLED (JERRY_BUILTIN_REGEXP) */
2391 JERRY_UNUSED (pattern_p);
2392 JERRY_UNUSED (pattern_size);
2393 JERRY_UNUSED (flags);
2394
2395 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("RegExp is not supported.")));
2396#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
2397} /* jerry_create_regexp_sz */
2398
2399/**
2400 * Creates a new realm (global object).
2401 *
2402 * @return new realm object
2403 */
2404jerry_value_t
2405jerry_create_realm (void)
2406{
2407 jerry_assert_api_available ();
2408
2409#if ENABLED (JERRY_BUILTIN_REALMS)
2410 ecma_global_object_t *global_object_p = ecma_builtin_create_global_object ();
2411 return ecma_make_object_value ((ecma_object_t *) global_object_p);
2412#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
2413 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Realms are disabled.")));
2414#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
2415} /* jerry_create_realm */
2416
2417/**
2418 * Get length of an array object
2419 *
2420 * Note:
2421 * Returns 0, if the value parameter is not an array object.
2422 *
2423 * @return length of the given array
2424 */
2425uint32_t
2426jerry_get_array_length (const jerry_value_t value) /**< api value */
2427{
2428 jerry_assert_api_available ();
2429
2430 if (!jerry_value_is_object (value))
2431 {
2432 return 0;
2433 }
2434
2435 ecma_object_t *object_p = ecma_get_object_from_value (value);
2436
2437 if (JERRY_LIKELY (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY))
2438 {
2439 return ecma_array_get_length (object_p);
2440 }
2441
2442 return 0;
2443} /* jerry_get_array_length */
2444
2445/**
2446 * Get size of Jerry string
2447 *
2448 * Note:
2449 * Returns 0, if the value parameter is not a string.
2450 *
2451 * @return number of bytes in the buffer needed to represent the string
2452 */
2453jerry_size_t
2454jerry_get_string_size (const jerry_value_t value) /**< input string */
2455{
2456 jerry_assert_api_available ();
2457
2458 if (!ecma_is_value_string (value))
2459 {
2460 return 0;
2461 }
2462
2463 return ecma_string_get_size (ecma_get_string_from_value (value));
2464} /* jerry_get_string_size */
2465
2466/**
2467 * Get UTF-8 encoded string size from Jerry string
2468 *
2469 * Note:
2470 * Returns 0, if the value parameter is not a string.
2471 *
2472 * @return number of bytes in the buffer needed to represent the UTF-8 encoded string
2473 */
2474jerry_size_t
2475jerry_get_utf8_string_size (const jerry_value_t value) /**< input string */
2476{
2477 jerry_assert_api_available ();
2478
2479 if (!ecma_is_value_string (value))
2480 {
2481 return 0;
2482 }
2483
2484 return ecma_string_get_utf8_size (ecma_get_string_from_value (value));
2485} /* jerry_get_utf8_string_size */
2486
2487/**
2488 * Get length of Jerry string
2489 *
2490 * Note:
2491 * Returns 0, if the value parameter is not a string.
2492 *
2493 * @return number of characters in the string
2494 */
2495jerry_length_t
2496jerry_get_string_length (const jerry_value_t value) /**< input string */
2497{
2498 jerry_assert_api_available ();
2499
2500 if (!ecma_is_value_string (value))
2501 {
2502 return 0;
2503 }
2504
2505 return ecma_string_get_length (ecma_get_string_from_value (value));
2506} /* jerry_get_string_length */
2507
2508/**
2509 * Get UTF-8 string length from Jerry string
2510 *
2511 * Note:
2512 * Returns 0, if the value parameter is not a string.
2513 *
2514 * @return number of characters in the string
2515 */
2516jerry_length_t
2517jerry_get_utf8_string_length (const jerry_value_t value) /**< input string */
2518{
2519 jerry_assert_api_available ();
2520
2521 if (!ecma_is_value_string (value))
2522 {
2523 return 0;
2524 }
2525
2526 return ecma_string_get_utf8_length (ecma_get_string_from_value (value));
2527} /* jerry_get_utf8_string_length */
2528
2529/**
2530 * Copy the characters of a string into a specified buffer.
2531 *
2532 * Note:
2533 * The '\0' character could occur in character buffer.
2534 * Returns 0, if the value parameter is not a string or
2535 * the buffer is not large enough for the whole string.
2536 *
2537 * Note:
2538 * If the size of the string in jerry value is larger than the size of the
2539 * target buffer, the copy will fail.
2540 * To copy substring use jerry_substring_to_char_buffer() instead.
2541 *
2542 * @return number of bytes, actually copied to the buffer.
2543 */
2544jerry_size_t
2545jerry_string_to_char_buffer (const jerry_value_t value, /**< input string value */
2546 jerry_char_t *buffer_p, /**< [out] output characters buffer */
2547 jerry_size_t buffer_size) /**< size of output buffer */
2548{
2549 jerry_assert_api_available ();
2550
2551 if (!ecma_is_value_string (value) || buffer_p == NULL)
2552 {
2553 return 0;
2554 }
2555
2556 ecma_string_t *str_p = ecma_get_string_from_value (value);
2557
2558 if (ecma_string_get_size (str_p) > buffer_size)
2559 {
2560 return 0;
2561 }
2562
2563 return ecma_string_copy_to_cesu8_buffer (str_p,
2564 (lit_utf8_byte_t *) buffer_p,
2565 buffer_size);
2566} /* jerry_string_to_char_buffer */
2567
2568/**
2569 * Copy the characters of an utf-8 encoded string into a specified buffer.
2570 *
2571 * Note:
2572 * The '\0' character could occur anywhere in the returned string
2573 * Returns 0, if the value parameter is not a string or the buffer
2574 * is not large enough for the whole string.
2575 *
2576 * Note:
2577 * If the size of the string in jerry value is larger than the size of the
2578 * target buffer, the copy will fail.
2579 * To copy a substring use jerry_substring_to_utf8_char_buffer() instead.
2580 *
2581 * @return number of bytes copied to the buffer.
2582 */
2583jerry_size_t
2584jerry_string_to_utf8_char_buffer (const jerry_value_t value, /**< input string value */
2585 jerry_char_t *buffer_p, /**< [out] output characters buffer */
2586 jerry_size_t buffer_size) /**< size of output buffer */
2587{
2588 jerry_assert_api_available ();
2589
2590 if (!ecma_is_value_string (value) || buffer_p == NULL)
2591 {
2592 return 0;
2593 }
2594
2595 ecma_string_t *str_p = ecma_get_string_from_value (value);
2596
2597 if (ecma_string_get_utf8_size (str_p) > buffer_size)
2598 {
2599 return 0;
2600 }
2601
2602 return ecma_string_copy_to_utf8_buffer (str_p,
2603 (lit_utf8_byte_t *) buffer_p,
2604 buffer_size);
2605} /* jerry_string_to_utf8_char_buffer */
2606
2607/**
2608 * Copy the characters of an cesu-8 encoded substring into a specified buffer.
2609 *
2610 * Note:
2611 * The '\0' character could occur anywhere in the returned string
2612 * Returns 0, if the value parameter is not a string.
2613 * It will extract the substring beetween the specified start position
2614 * and the end position (or the end of the string, whichever comes first).
2615 *
2616 * @return number of bytes copied to the buffer.
2617 */
2618jerry_size_t
2619jerry_substring_to_char_buffer (const jerry_value_t value, /**< input string value */
2620 jerry_length_t start_pos, /**< position of the first character */
2621 jerry_length_t end_pos, /**< position of the last character */
2622 jerry_char_t *buffer_p, /**< [out] output characters buffer */
2623 jerry_size_t buffer_size) /**< size of output buffer */
2624{
2625 jerry_assert_api_available ();
2626
2627 if (!ecma_is_value_string (value) || buffer_p == NULL)
2628 {
2629 return 0;
2630 }
2631
2632 ecma_string_t *str_p = ecma_get_string_from_value (value);
2633
2634 return ecma_substring_copy_to_cesu8_buffer (str_p,
2635 start_pos,
2636 end_pos,
2637 (lit_utf8_byte_t *) buffer_p,
2638 buffer_size);
2639} /* jerry_substring_to_char_buffer */
2640
2641/**
2642 * Copy the characters of an utf-8 encoded substring into a specified buffer.
2643 *
2644 * Note:
2645 * The '\0' character could occur anywhere in the returned string
2646 * Returns 0, if the value parameter is not a string.
2647 * It will extract the substring beetween the specified start position
2648 * and the end position (or the end of the string, whichever comes first).
2649 *
2650 * @return number of bytes copied to the buffer.
2651 */
2652jerry_size_t
2653jerry_substring_to_utf8_char_buffer (const jerry_value_t value, /**< input string value */
2654 jerry_length_t start_pos, /**< position of the first character */
2655 jerry_length_t end_pos, /**< position of the last character */
2656 jerry_char_t *buffer_p, /**< [out] output characters buffer */
2657 jerry_size_t buffer_size) /**< size of output buffer */
2658{
2659 jerry_assert_api_available ();
2660
2661 if (!ecma_is_value_string (value) || buffer_p == NULL)
2662 {
2663 return 0;
2664 }
2665
2666 ecma_string_t *str_p = ecma_get_string_from_value (value);
2667
2668 return ecma_substring_copy_to_utf8_buffer (str_p,
2669 start_pos,
2670 end_pos,
2671 (lit_utf8_byte_t *) buffer_p,
2672 buffer_size);
2673} /* jerry_substring_to_utf8_char_buffer */
2674
2675/**
2676 * Checks whether the object or it's prototype objects have the given property.
2677 *
2678 * @return raised error - if the operation fail
2679 * true/false API value - depend on whether the property exists
2680 */
2681jerry_value_t
2682jerry_has_property (const jerry_value_t obj_val, /**< object value */
2683 const jerry_value_t prop_name_val) /**< property name (string value) */
2684{
2685 jerry_assert_api_available ();
2686
2687 if (!ecma_is_value_object (obj_val)
2688 || !ecma_is_value_prop_name (prop_name_val))
2689 {
2690 return ECMA_VALUE_FALSE;
2691 }
2692
2693 return jerry_return (ecma_op_object_has_property (ecma_get_object_from_value (obj_val),
2694 ecma_get_prop_name_from_value (prop_name_val)));
2695} /* jerry_has_property */
2696
2697/**
2698 * Checks whether the object has the given property.
2699 *
2700 * @return ECMA_VALUE_ERROR - if the operation raises error
2701 * ECMA_VALUE_{TRUE, FALSE} - based on whether the property exists
2702 */
2703jerry_value_t
2704jerry_has_own_property (const jerry_value_t obj_val, /**< object value */
2705 const jerry_value_t prop_name_val) /**< property name (string value) */
2706{
2707 jerry_assert_api_available ();
2708
2709 if (!ecma_is_value_object (obj_val)
2710 || !ecma_is_value_prop_name (prop_name_val))
2711 {
2712 return ECMA_VALUE_FALSE;
2713 }
2714
2715 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2716 ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (prop_name_val);
2717
2718#if ENABLED (JERRY_BUILTIN_PROXY)
2719 if (ECMA_OBJECT_IS_PROXY (obj_p))
2720 {
2721 ecma_property_descriptor_t prop_desc;
2722
2723 ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc);
2724
2725 if (ecma_is_value_true (status))
2726 {
2727 ecma_free_property_descriptor (&prop_desc);
2728 }
2729
2730 return jerry_return (status);
2731 }
2732#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
2733
2734 return ecma_make_boolean_value (ecma_op_ordinary_object_has_own_property (obj_p, prop_name_p));
2735} /* jerry_has_own_property */
2736
2737/**
2738 * Checks whether the object has the given internal property.
2739 *
2740 * @return true - if the internal property exists
2741 * false - otherwise
2742 */
2743bool
2744jerry_has_internal_property (const jerry_value_t obj_val, /**< object value */
2745 const jerry_value_t prop_name_val) /**< property name value */
2746{
2747 jerry_assert_api_available ();
2748
2749 if (!ecma_is_value_object (obj_val)
2750 || !ecma_is_value_prop_name (prop_name_val))
2751 {
2752 return false;
2753 }
2754
2755 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2756
2757 ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
2758
2759 if (ecma_op_object_is_fast_array (obj_p))
2760 {
2761 return false;
2762 }
2763
2764 ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
2765
2766 if (property_p == NULL)
2767 {
2768 return false;
2769 }
2770
2771 ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
2772 property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (prop_name_val));
2773
2774 return property_p != NULL;
2775} /* jerry_has_internal_property */
2776
2777/**
2778 * Delete a property from an object.
2779 *
2780 * @return true - if property was deleted successfully
2781 * false - otherwise
2782 */
2783bool
2784jerry_delete_property (const jerry_value_t obj_val, /**< object value */
2785 const jerry_value_t prop_name_val) /**< property name (string value) */
2786{
2787 jerry_assert_api_available ();
2788
2789 if (!ecma_is_value_object (obj_val)
2790 || !ecma_is_value_prop_name (prop_name_val))
2791 {
2792 return false;
2793 }
2794
2795 ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val),
2796 ecma_get_prop_name_from_value (prop_name_val),
2797 false);
2798
2799#if ENABLED (JERRY_BUILTIN_PROXY)
2800 if (ECMA_IS_VALUE_ERROR (ret_value))
2801 {
2802 // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
2803 jcontext_release_exception ();
2804 }
2805#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
2806
2807 return ecma_is_value_true (ret_value);
2808} /* jerry_delete_property */
2809
2810/**
2811 * Delete indexed property from the specified object.
2812 *
2813 * @return true - if property was deleted successfully
2814 * false - otherwise
2815 */
2816bool
2817jerry_delete_property_by_index (const jerry_value_t obj_val, /**< object value */
2818 uint32_t index) /**< index to be written */
2819{
2820 jerry_assert_api_available ();
2821
2822 if (!ecma_is_value_object (obj_val))
2823 {
2824 return false;
2825 }
2826
2827 ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index);
2828 ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val),
2829 str_idx_p,
2830 false);
2831 ecma_deref_ecma_string (str_idx_p);
2832
2833#if ENABLED (JERRY_BUILTIN_PROXY)
2834 if (ECMA_IS_VALUE_ERROR (ret_value))
2835 {
2836 // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
2837 jcontext_release_exception ();
2838 }
2839#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
2840
2841 return ecma_is_value_true (ret_value);
2842} /* jerry_delete_property_by_index */
2843
2844/**
2845 * Delete an internal property from an object.
2846 *
2847 * @return true - if property was deleted successfully
2848 * false - otherwise
2849 */
2850bool
2851jerry_delete_internal_property (const jerry_value_t obj_val, /**< object value */
2852 const jerry_value_t prop_name_val) /**< property name value */
2853{
2854 jerry_assert_api_available ();
2855
2856 if (!ecma_is_value_object (obj_val)
2857 || !ecma_is_value_prop_name (prop_name_val))
2858 {
2859 return false;
2860 }
2861
2862 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2863
2864 ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
2865
2866 if (ecma_op_object_is_fast_array (obj_p))
2867 {
2868 return true;
2869 }
2870
2871 ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
2872
2873 if (property_p == NULL)
2874 {
2875 return true;
2876 }
2877
2878 ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
2879 property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (prop_name_val));
2880
2881 if (property_p == NULL)
2882 {
2883 return true;
2884 }
2885
2886 ecma_delete_property (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p));
2887
2888 return true;
2889} /* jerry_delete_internal_property */
2890
2891/**
2892 * Get value of a property to the specified object with the given name.
2893 *
2894 * Note:
2895 * returned value must be freed with jerry_release_value, when it is no longer needed.
2896 *
2897 * @return value of the property - if success
2898 * value marked with error flag - otherwise
2899 */
2900jerry_value_t
2901jerry_get_property (const jerry_value_t obj_val, /**< object value */
2902 const jerry_value_t prop_name_val) /**< property name (string value) */
2903{
2904 jerry_assert_api_available ();
2905
2906 if (!ecma_is_value_object (obj_val)
2907 || !ecma_is_value_prop_name (prop_name_val))
2908 {
2909 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2910 }
2911
2912 jerry_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_val),
2913 ecma_get_prop_name_from_value (prop_name_val));
2914 return jerry_return (ret_value);
2915} /* jerry_get_property */
2916
2917/**
2918 * Get value by an index from the specified object.
2919 *
2920 * Note:
2921 * returned value must be freed with jerry_release_value, when it is no longer needed.
2922 *
2923 * @return value of the property specified by the index - if success
2924 * value marked with error flag - otherwise
2925 */
2926jerry_value_t
2927jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */
2928 uint32_t index) /**< index to be written */
2929{
2930 jerry_assert_api_available ();
2931
2932 if (!ecma_is_value_object (obj_val))
2933 {
2934 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2935 }
2936
2937 ecma_value_t ret_value = ecma_op_object_get_by_index (ecma_get_object_from_value (obj_val), index);
2938
2939 return jerry_return (ret_value);
2940} /* jerry_get_property_by_index */
2941
2942/**
2943 * Get value of an internal property to the specified object with the given name.
2944 *
2945 * Note:
2946 * returned value must be freed with jerry_release_value, when it is no longer needed.
2947 *
2948 * @return value of the internal property - if the internal property exists
2949 * undefined value - if the internal does not property exists
2950 * value marked with error flag - otherwise
2951 */
2952jerry_value_t
2953jerry_get_internal_property (const jerry_value_t obj_val, /**< object value */
2954 const jerry_value_t prop_name_val) /**< property name value */
2955{
2956 jerry_assert_api_available ();
2957
2958 if (!ecma_is_value_object (obj_val)
2959 || !ecma_is_value_prop_name (prop_name_val))
2960 {
2961 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2962 }
2963
2964 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2965
2966 ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
2967
2968 if (ecma_op_object_is_fast_array (obj_p))
2969 {
2970 return jerry_return (ECMA_VALUE_UNDEFINED);
2971 }
2972
2973 ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
2974
2975 if (property_p == NULL)
2976 {
2977 return jerry_return (ECMA_VALUE_UNDEFINED);
2978 }
2979
2980 ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
2981 property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (prop_name_val));
2982
2983 if (property_p == NULL)
2984 {
2985 return jerry_return (ECMA_VALUE_UNDEFINED);
2986 }
2987
2988 return jerry_return (ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value));
2989} /* jerry_get_internal_property */
2990
2991/**
2992 * Set a property to the specified object with the given name.
2993 *
2994 * Note:
2995 * returned value must be freed with jerry_release_value, when it is no longer needed.
2996 *
2997 * @return true value - if the operation was successful
2998 * value marked with error flag - otherwise
2999 */
3000jerry_value_t
3001jerry_set_property (const jerry_value_t obj_val, /**< object value */
3002 const jerry_value_t prop_name_val, /**< property name (string value) */
3003 const jerry_value_t value_to_set) /**< value to set */
3004{
3005 jerry_assert_api_available ();
3006
3007 if (ecma_is_value_error_reference (value_to_set)
3008 || !ecma_is_value_object (obj_val)
3009 || !ecma_is_value_prop_name (prop_name_val))
3010 {
3011 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3012 }
3013
3014 return jerry_return (ecma_op_object_put (ecma_get_object_from_value (obj_val),
3015 ecma_get_prop_name_from_value (prop_name_val),
3016 value_to_set,
3017 true));
3018} /* jerry_set_property */
3019
3020/**
3021 * Set indexed value in the specified object
3022 *
3023 * Note:
3024 * returned value must be freed with jerry_release_value, when it is no longer needed.
3025 *
3026 * @return true value - if the operation was successful
3027 * value marked with error flag - otherwise
3028 */
3029jerry_value_t
3030jerry_set_property_by_index (const jerry_value_t obj_val, /**< object value */
3031 uint32_t index, /**< index to be written */
3032 const jerry_value_t value_to_set) /**< value to set */
3033{
3034 jerry_assert_api_available ();
3035
3036 if (ecma_is_value_error_reference (value_to_set)
3037 || !ecma_is_value_object (obj_val))
3038 {
3039 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3040 }
3041
3042 ecma_value_t ret_value = ecma_op_object_put_by_index (ecma_get_object_from_value (obj_val),
3043 index,
3044 value_to_set,
3045 true);
3046
3047 return jerry_return (ret_value);
3048} /* jerry_set_property_by_index */
3049
3050/**
3051 * Set an internal property to the specified object with the given name.
3052 *
3053 * Note:
3054 * - the property cannot be accessed from the JavaScript context, only from the public API
3055 * - returned value must be freed with jerry_release_value, when it is no longer needed.
3056 *
3057 * @return true value - if the operation was successful
3058 * value marked with error flag - otherwise
3059 */
3060bool
3061jerry_set_internal_property (const jerry_value_t obj_val, /**< object value */
3062 const jerry_value_t prop_name_val, /**< property name value */
3063 const jerry_value_t value_to_set) /**< value to set */
3064{
3065 jerry_assert_api_available ();
3066
3067 if (ecma_is_value_error_reference (value_to_set)
3068 || !ecma_is_value_object (obj_val)
3069 || !ecma_is_value_prop_name (prop_name_val))
3070 {
3071 return false;
3072 }
3073
3074 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
3075
3076 ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
3077
3078 if (ecma_op_object_is_fast_array (obj_p))
3079 {
3080 ecma_fast_array_convert_to_normal (obj_p);
3081 }
3082
3083 ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
3084 ecma_object_t *internal_object_p;
3085
3086 if (property_p == NULL)
3087 {
3088 ecma_property_value_t *value_p = ecma_create_named_data_property (obj_p,
3089 internal_string_p,
3090 ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
3091 NULL);
3092
3093 internal_object_p = ecma_create_object (NULL,
3094 sizeof (ecma_extended_object_t),
3095 ECMA_OBJECT_TYPE_CLASS);
3096 {
3097 ecma_extended_object_t *container_p = (ecma_extended_object_t *) internal_object_p;
3098 container_p->u.class_prop.class_id = LIT_INTERNAL_MAGIC_STRING_INTERNAL_OBJECT;
3099 container_p->u.class_prop.extra_info = 0;
3100 container_p->u.class_prop.u.length = 0;
3101 }
3102
3103 value_p->value = ecma_make_object_value (internal_object_p);
3104 ecma_deref_object (internal_object_p);
3105 }
3106 else
3107 {
3108 internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
3109 }
3110
3111 ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (prop_name_val);
3112 property_p = ecma_find_named_property (internal_object_p, prop_name_p);
3113
3114 if (property_p == NULL)
3115 {
3116 ecma_property_value_t *value_p = ecma_create_named_data_property (internal_object_p,
3117 prop_name_p,
3118 ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
3119 NULL);
3120
3121 value_p->value = ecma_copy_value_if_not_object (value_to_set);
3122 }
3123 else
3124 {
3125 ecma_named_data_property_assign_value (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value_to_set);
3126 }
3127
3128 return true;
3129} /* jerry_set_internal_property */
3130
3131/**
3132 * Initialize property descriptor.
3133 */
3134void
3135jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p) /**< [out] property descriptor */
3136{
3137 prop_desc_p->is_value_defined = false;
3138 prop_desc_p->value = ECMA_VALUE_UNDEFINED;
3139 prop_desc_p->is_writable_defined = false;
3140 prop_desc_p->is_writable = false;
3141 prop_desc_p->is_enumerable_defined = false;
3142 prop_desc_p->is_enumerable = false;
3143 prop_desc_p->is_configurable_defined = false;
3144 prop_desc_p->is_configurable = false;
3145 prop_desc_p->is_get_defined = false;
3146 prop_desc_p->getter = ECMA_VALUE_UNDEFINED;
3147 prop_desc_p->is_set_defined = false;
3148 prop_desc_p->setter = ECMA_VALUE_UNDEFINED;
3149} /* jerry_init_property_descriptor_fields */
3150
3151/**
3152 * Convert a ecma_property_descriptor_t to a jerry_property_descriptor_t
3153 *
3154 * if error occurs the property descriptor's value field is filled with ECMA_VALUE_ERROR
3155 *
3156 * @return jerry_property_descriptor_t
3157 */
3158static jerry_property_descriptor_t
3159jerry_property_descriptor_from_ecma (const ecma_property_descriptor_t *prop_desc_p) /**<[out] property_descriptor */
3160{
3161 jerry_property_descriptor_t prop_desc;
3162 jerry_init_property_descriptor_fields (&prop_desc);
3163
3164 if (prop_desc_p->flags & (ECMA_PROP_IS_ENUMERABLE_DEFINED))
3165 {
3166 prop_desc.is_enumerable_defined = true;
3167 prop_desc.is_enumerable = prop_desc_p->flags & (ECMA_PROP_IS_ENUMERABLE);
3168 }
3169
3170 if (prop_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE_DEFINED))
3171 {
3172 prop_desc.is_configurable_defined = true;
3173 prop_desc.is_configurable = prop_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE);
3174 }
3175
3176 prop_desc.is_value_defined = prop_desc_p->flags & (ECMA_PROP_IS_VALUE_DEFINED);
3177
3178 if (prop_desc.is_value_defined)
3179 {
3180 prop_desc.value = prop_desc_p->value;
3181 }
3182
3183 if (prop_desc_p->flags & (ECMA_PROP_IS_WRITABLE_DEFINED))
3184 {
3185 prop_desc.is_writable_defined = true;
3186 prop_desc.is_writable = prop_desc_p->flags & (ECMA_PROP_IS_WRITABLE);
3187 }
3188
3189 if (prop_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED))
3190 {
3191 ecma_value_t getter = ecma_make_object_value (prop_desc_p->get_p);
3192 prop_desc.is_get_defined = true;
3193
3194 if (ecma_op_is_callable (getter))
3195 {
3196 prop_desc.getter = getter;
3197 }
3198 }
3199
3200 if (prop_desc_p->flags & (ECMA_PROP_IS_SET_DEFINED))
3201 {
3202 ecma_value_t setter = ecma_make_object_value (prop_desc_p->set_p);
3203 prop_desc.is_set_defined = true;
3204 prop_desc.setter = setter;
3205 }
3206
3207 return prop_desc;
3208} /* jerry_property_descriptor_from_ecma */
3209
3210/**
3211 * Convert a jerry_property_descriptor_t to a ecma_property_descriptor_t
3212 *
3213 * if error occurs the property descriptor's value field is filled with ECMA_VALUE_ERROR
3214 *
3215 * @return ecma_property_descriptor_t
3216 */
3217static ecma_property_descriptor_t
3218jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_p) /**< input property_descriptor */
3219{
3220 ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
3221
3222 uint32_t flags = ECMA_PROP_NO_OPTS;
3223
3224 if (prop_desc_p->is_enumerable_defined)
3225 {
3226 flags |= (uint32_t) (ECMA_PROP_IS_ENUMERABLE_DEFINED | (prop_desc_p->is_enumerable ? ECMA_PROP_IS_ENUMERABLE
3227 : ECMA_PROP_NO_OPTS));
3228 }
3229
3230 if (prop_desc_p->is_configurable_defined)
3231 {
3232 flags |= (uint32_t) (ECMA_PROP_IS_CONFIGURABLE_DEFINED | (prop_desc_p->is_configurable ? ECMA_PROP_IS_CONFIGURABLE
3233 : ECMA_PROP_NO_OPTS));
3234 }
3235
3236 /* Copy data property info. */
3237 flags |= (prop_desc_p->is_value_defined ? ECMA_PROP_IS_VALUE_DEFINED : ECMA_PROP_NO_OPTS);
3238
3239 if (prop_desc_p->is_value_defined)
3240 {
3241 if (ecma_is_value_error_reference (prop_desc_p->value))
3242 {
3243 prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
3244 return prop_desc;
3245 }
3246
3247 prop_desc.value = prop_desc_p->value;
3248 }
3249
3250 if (prop_desc_p->is_writable_defined)
3251 {
3252 flags |= (uint32_t) (ECMA_PROP_IS_WRITABLE_DEFINED | (prop_desc_p->is_writable ? ECMA_PROP_IS_WRITABLE
3253 : ECMA_PROP_NO_OPTS));
3254 }
3255
3256 /* Copy accessor property info. */
3257 if (prop_desc_p->is_get_defined)
3258 {
3259 ecma_value_t getter = prop_desc_p->getter;
3260 flags |= ECMA_PROP_IS_GET_DEFINED;
3261
3262 if (ecma_is_value_error_reference (getter))
3263 {
3264 prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
3265 return prop_desc;
3266 }
3267
3268 if (ecma_op_is_callable (getter))
3269 {
3270 prop_desc.get_p = ecma_get_object_from_value (getter);
3271 }
3272 else if (!ecma_is_value_null (getter))
3273 {
3274 prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
3275 return prop_desc;
3276 }
3277 }
3278
3279 if (prop_desc_p->is_set_defined)
3280 {
3281 ecma_value_t setter = prop_desc_p->setter;
3282 flags |= ECMA_PROP_IS_SET_DEFINED;
3283
3284 if (ecma_is_value_error_reference (setter))
3285 {
3286 prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
3287 return prop_desc;
3288 }
3289
3290 if (ecma_op_is_callable (setter))
3291 {
3292 prop_desc.set_p = ecma_get_object_from_value (setter);
3293 }
3294 else if (!ecma_is_value_null (setter))
3295 {
3296 prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
3297 return prop_desc;
3298 }
3299 }
3300
3301 prop_desc.flags |= (uint16_t) (flags | ECMA_PROP_IS_THROW);
3302
3303 return prop_desc;
3304} /* jerry_property_descriptor_to_ecma */
3305
3306/**
3307 * Define a property to the specified object with the given name.
3308 *
3309 * Note:
3310 * returned value must be freed with jerry_release_value, when it is no longer needed.
3311 *
3312 * @return true value - if the operation was successful
3313 * value marked with error flag - otherwise
3314 */
3315jerry_value_t
3316jerry_define_own_property (const jerry_value_t obj_val, /**< object value */
3317 const jerry_value_t prop_name_val, /**< property name (string value) */
3318 const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */
3319{
3320 jerry_assert_api_available ();
3321
3322 if (!ecma_is_value_object (obj_val)
3323 || !ecma_is_value_prop_name (prop_name_val))
3324 {
3325 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3326 }
3327
3328 if ((prop_desc_p->is_writable_defined || prop_desc_p->is_value_defined)
3329 && (prop_desc_p->is_get_defined || prop_desc_p->is_set_defined))
3330 {
3331 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3332 }
3333
3334 ecma_property_descriptor_t prop_desc = jerry_property_descriptor_to_ecma (prop_desc_p);
3335
3336 if (ECMA_IS_VALUE_ERROR (prop_desc.value))
3337 {
3338 return jerry_throw (prop_desc.value);
3339 }
3340 return jerry_return (ecma_op_object_define_own_property (ecma_get_object_from_value (obj_val),
3341 ecma_get_prop_name_from_value (prop_name_val),
3342 &prop_desc));
3343} /* jerry_define_own_property */
3344
3345/**
3346 * Construct property descriptor from specified property.
3347 *
3348 * @return true - if success, the prop_desc_p fields contains the property info
3349 * false - otherwise, the prop_desc_p is unchanged
3350 */
3351bool
3352jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object value */
3353 const jerry_value_t prop_name_val, /**< property name (string value) */
3354 jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */
3355{
3356 jerry_assert_api_available ();
3357
3358 if (!ecma_is_value_object (obj_val)
3359 || !ecma_is_value_prop_name (prop_name_val))
3360 {
3361 return false;
3362 }
3363
3364 ecma_property_descriptor_t prop_desc;
3365
3366 ecma_value_t status = ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_val),
3367 ecma_get_prop_name_from_value (prop_name_val),
3368 &prop_desc);
3369
3370#if ENABLED (JERRY_BUILTIN_PROXY)
3371 if (ECMA_IS_VALUE_ERROR (status))
3372 {
3373 // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
3374 jcontext_release_exception ();
3375 }
3376#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
3377
3378 if (!ecma_is_value_true (status))
3379 {
3380 return false;
3381 }
3382
3383 prop_desc_p->is_configurable_defined = true;
3384 prop_desc_p->is_configurable = (prop_desc.flags & ECMA_PROP_IS_CONFIGURABLE) != 0;
3385 prop_desc_p->is_enumerable_defined = true;
3386 prop_desc_p->is_enumerable = (prop_desc.flags & ECMA_PROP_IS_ENUMERABLE) != 0;
3387
3388 prop_desc_p->is_writable_defined = (prop_desc.flags & ECMA_PROP_IS_WRITABLE_DEFINED) != 0;
3389 prop_desc_p->is_writable = prop_desc_p->is_writable_defined ? (prop_desc.flags & ECMA_PROP_IS_WRITABLE) != 0 : false;
3390
3391 prop_desc_p->is_value_defined = (prop_desc.flags & ECMA_PROP_IS_VALUE_DEFINED) != 0;
3392 prop_desc_p->is_get_defined = (prop_desc.flags & ECMA_PROP_IS_GET_DEFINED) != 0;
3393 prop_desc_p->is_set_defined = (prop_desc.flags & ECMA_PROP_IS_SET_DEFINED) != 0;
3394
3395 prop_desc_p->value = ECMA_VALUE_UNDEFINED;
3396 prop_desc_p->getter = ECMA_VALUE_UNDEFINED;
3397 prop_desc_p->setter = ECMA_VALUE_UNDEFINED;
3398
3399 if (prop_desc_p->is_value_defined)
3400 {
3401 prop_desc_p->value = prop_desc.value;
3402 }
3403
3404 if (prop_desc_p->is_get_defined)
3405 {
3406 if (prop_desc.get_p != NULL)
3407 {
3408 prop_desc_p->getter = ecma_make_object_value (prop_desc.get_p);
3409 }
3410 else
3411 {
3412 prop_desc_p->getter = ECMA_VALUE_NULL;
3413 }
3414 }
3415
3416 if (prop_desc_p->is_set_defined)
3417 {
3418 if (prop_desc.set_p != NULL)
3419 {
3420 prop_desc_p->setter = ecma_make_object_value (prop_desc.set_p);
3421 }
3422 else
3423 {
3424 prop_desc_p->setter = ECMA_VALUE_NULL;
3425 }
3426 }
3427
3428 return true;
3429} /* jerry_get_own_property_descriptor */
3430
3431/**
3432 * Free fields of property descriptor (setter, getter and value).
3433 */
3434void
3435jerry_free_property_descriptor_fields (const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */
3436{
3437 if (prop_desc_p->is_value_defined)
3438 {
3439 jerry_release_value (prop_desc_p->value);
3440 }
3441
3442 if (prop_desc_p->is_get_defined)
3443 {
3444 jerry_release_value (prop_desc_p->getter);
3445 }
3446
3447 if (prop_desc_p->is_set_defined)
3448 {
3449 jerry_release_value (prop_desc_p->setter);
3450 }
3451} /* jerry_free_property_descriptor_fields */
3452
3453/**
3454 * Invoke function specified by a function value
3455 *
3456 * Note:
3457 * - returned value must be freed with jerry_release_value, when it is no longer needed.
3458 * - If function is invoked as constructor, it should support [[Construct]] method,
3459 * otherwise, if function is simply called - it should support [[Call]] method.
3460 *
3461 * @return returned jerry value of the invoked function
3462 */
3463static jerry_value_t
3464jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke function as constructor
3465 * (this_arg_p should be NULL, as it is ignored),
3466 * false - perform function call */
3467 const jerry_value_t func_obj_val, /**< function object to call */
3468 const jerry_value_t this_val, /**< object value of 'this' binding */
3469 const jerry_value_t args_p[], /**< function's call arguments */
3470 const jerry_size_t args_count) /**< number of the arguments */
3471{
3472 JERRY_ASSERT (args_count == 0 || args_p != NULL);
3473
3474 if (ecma_is_value_error_reference (func_obj_val)
3475 || ecma_is_value_error_reference (this_val))
3476 {
3477 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
3478 }
3479
3480 for (uint32_t i = 0; i < args_count; i++)
3481 {
3482 if (ecma_is_value_error_reference (args_p[i]))
3483 {
3484 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
3485 }
3486 }
3487
3488 if (is_invoke_as_constructor)
3489 {
3490 JERRY_ASSERT (jerry_value_is_constructor (func_obj_val));
3491
3492 return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_obj_val),
3493 ecma_get_object_from_value (func_obj_val),
3494 args_p,
3495 args_count));
3496 }
3497 else
3498 {
3499 JERRY_ASSERT (jerry_value_is_function (func_obj_val));
3500
3501 return jerry_return (ecma_op_function_call (ecma_get_object_from_value (func_obj_val),
3502 this_val,
3503 args_p,
3504 args_count));
3505 }
3506} /* jerry_invoke_function */
3507
3508/**
3509 * Call function specified by a function value
3510 *
3511 * Note:
3512 * returned value must be freed with jerry_release_value, when it is no longer needed.
3513 * error flag must not be set for any arguments of this function.
3514 *
3515 * @return returned jerry value of the called function
3516 */
3517jerry_value_t
3518jerry_call_function (const jerry_value_t func_obj_val, /**< function object to call */
3519 const jerry_value_t this_val, /**< object for 'this' binding */
3520 const jerry_value_t args_p[], /**< function's call arguments */
3521 jerry_size_t args_count) /**< number of the arguments */
3522{
3523 jerry_assert_api_available ();
3524
3525 if (jerry_value_is_function (func_obj_val) && !ecma_is_value_error_reference (this_val))
3526 {
3527 for (jerry_size_t i = 0; i < args_count; i++)
3528 {
3529 if (ecma_is_value_error_reference (args_p[i]))
3530 {
3531 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
3532 }
3533 }
3534
3535 return jerry_invoke_function (false, func_obj_val, this_val, args_p, args_count);
3536 }
3537
3538 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3539} /* jerry_call_function */
3540
3541/**
3542 * Construct object value invoking specified function value as a constructor
3543 *
3544 * Note:
3545 * returned value must be freed with jerry_release_value, when it is no longer needed.
3546 * error flag must not be set for any arguments of this function.
3547 *
3548 * @return returned jerry value of the invoked constructor
3549 */
3550jerry_value_t
3551jerry_construct_object (const jerry_value_t func_obj_val, /**< function object to call */
3552 const jerry_value_t args_p[], /**< function's call arguments
3553 * (NULL if arguments number is zero) */
3554 jerry_size_t args_count) /**< number of the arguments */
3555{
3556 jerry_assert_api_available ();
3557
3558 if (jerry_value_is_constructor (func_obj_val))
3559 {
3560 for (jerry_size_t i = 0; i < args_count; i++)
3561 {
3562 if (ecma_is_value_error_reference (args_p[i]))
3563 {
3564 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
3565 }
3566 }
3567
3568 ecma_value_t this_val = ECMA_VALUE_UNDEFINED;
3569 return jerry_invoke_function (true, func_obj_val, this_val, args_p, args_count);
3570 }
3571
3572 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3573} /* jerry_construct_object */
3574
3575/**
3576 * Get keys of the specified object value
3577 *
3578 * Note:
3579 * returned value must be freed with jerry_release_value, when it is no longer needed.
3580 *
3581 * @return array object value - if success
3582 * value marked with error flag - otherwise
3583 */
3584jerry_value_t
3585jerry_get_object_keys (const jerry_value_t obj_val) /**< object value */
3586{
3587 jerry_assert_api_available ();
3588
3589 if (!ecma_is_value_object (obj_val))
3590 {
3591 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3592 }
3593
3594 ecma_collection_t *prop_names = ecma_op_object_get_enumerable_property_names (ecma_get_object_from_value (obj_val),
3595 ECMA_ENUMERABLE_PROPERTY_KEYS);
3596
3597#if ENABLED (JERRY_BUILTIN_PROXY)
3598 if (JERRY_UNLIKELY (prop_names == NULL))
3599 {
3600 return ECMA_VALUE_ERROR;
3601 }
3602#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
3603
3604 return ecma_op_new_array_object_from_collection (prop_names, false);
3605} /* jerry_get_object_keys */
3606
3607/**
3608 * Get the prototype of the specified object
3609 *
3610 * Note:
3611 * returned value must be freed with jerry_release_value, when it is no longer needed.
3612 *
3613 * @return prototype object or null value - if success
3614 * value marked with error flag - otherwise
3615 */
3616jerry_value_t
3617jerry_get_prototype (const jerry_value_t obj_val) /**< object value */
3618{
3619 jerry_assert_api_available ();
3620
3621 if (!ecma_is_value_object (obj_val))
3622 {
3623 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3624 }
3625
3626 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
3627
3628#if ENABLED (JERRY_BUILTIN_PROXY)
3629 if (ECMA_OBJECT_IS_PROXY (obj_p))
3630 {
3631 return jerry_return (ecma_proxy_object_get_prototype_of (obj_p));
3632 }
3633#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
3634
3635 if (obj_p->u2.prototype_cp == JMEM_CP_NULL)
3636 {
3637 return ECMA_VALUE_NULL;
3638 }
3639
3640 ecma_object_t *proto_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_p->u2.prototype_cp);
3641 ecma_ref_object (proto_obj_p);
3642
3643 return ecma_make_object_value (proto_obj_p);
3644} /* jerry_get_prototype */
3645
3646/**
3647 * Set the prototype of the specified object
3648 *
3649 * @return true value - if success
3650 * value marked with error flag - otherwise
3651 */
3652jerry_value_t
3653jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
3654 const jerry_value_t proto_obj_val) /**< prototype object value */
3655{
3656 jerry_assert_api_available ();
3657
3658 if (!ecma_is_value_object (obj_val)
3659 || ecma_is_value_error_reference (proto_obj_val)
3660 || (!ecma_is_value_object (proto_obj_val) && !ecma_is_value_null (proto_obj_val)))
3661 {
3662 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3663 }
3664 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
3665
3666#if ENABLED (JERRY_BUILTIN_PROXY)
3667 if (ECMA_OBJECT_IS_PROXY (obj_p))
3668 {
3669 return jerry_return (ecma_proxy_object_set_prototype_of (obj_p, proto_obj_val));
3670 }
3671#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
3672
3673 return ecma_op_ordinary_object_set_prototype_of (obj_p, proto_obj_val);
3674} /* jerry_set_prototype */
3675
3676/**
3677 * Utility to check if a given object can be used for the foreach api calls.
3678 *
3679 * Some objects/classes uses extra internal objects to correctly store data.
3680 * These extre object should never be exposed externally to the API user.
3681 *
3682 * @returns true - if the user can access the object in the callback.
3683 * false - if the object is an internal object which should no be accessed by the user.
3684 */
3685static
3686bool jerry_object_is_valid_foreach (ecma_object_t *object_p) /**< object to test */
3687{
3688 if (ecma_is_lexical_environment (object_p))
3689 {
3690 return false;
3691 }
3692
3693 ecma_object_type_t object_type = ecma_get_object_type (object_p);
3694
3695 if (object_type == ECMA_OBJECT_TYPE_CLASS)
3696 {
3697 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
3698 switch (ext_object_p->u.class_prop.class_id)
3699 {
3700 /* An object's internal property object should not be iterable by foreach. */
3701 case LIT_INTERNAL_MAGIC_STRING_INTERNAL_OBJECT: return false;
3702 }
3703 }
3704
3705 return true;
3706} /* jerry_object_is_valid_foreach */
3707
3708/**
3709 * Traverse objects.
3710 *
3711 * @return true - traversal was interrupted by the callback.
3712 * false - otherwise - traversal visited all objects.
3713 */
3714bool
3715jerry_objects_foreach (jerry_objects_foreach_t foreach_p, /**< function pointer of the iterator function */
3716 void *user_data_p) /**< pointer to user data */
3717{
3718 jerry_assert_api_available ();
3719
3720 JERRY_ASSERT (foreach_p != NULL);
3721
3722 jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp);
3723
3724 while (iter_cp != JMEM_CP_NULL)
3725 {
3726 ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp);
3727
3728 if (jerry_object_is_valid_foreach (iter_p)
3729 && !foreach_p (ecma_make_object_value (iter_p), user_data_p))
3730 {
3731 return true;
3732 }
3733
3734 iter_cp = iter_p->gc_next_cp;
3735 }
3736
3737 return false;
3738} /* jerry_objects_foreach */
3739
3740/**
3741 * Traverse objects having a given native type info.
3742 *
3743 * @return true - traversal was interrupted by the callback.
3744 * false - otherwise - traversal visited all objects.
3745 */
3746bool
3747jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_info_p, /**< the type info
3748 * of the native pointer */
3749 jerry_objects_foreach_by_native_info_t foreach_p, /**< function to apply for
3750 * each matching object */
3751 void *user_data_p) /**< pointer to user data */
3752{
3753 jerry_assert_api_available ();
3754
3755 JERRY_ASSERT (native_info_p != NULL);
3756 JERRY_ASSERT (foreach_p != NULL);
3757
3758 ecma_native_pointer_t *native_pointer_p;
3759
3760 jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp);
3761
3762 while (iter_cp != JMEM_CP_NULL)
3763 {
3764 ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp);
3765
3766 if (jerry_object_is_valid_foreach (iter_p))
3767 {
3768 native_pointer_p = ecma_get_native_pointer_value (iter_p, (void *) native_info_p);
3769 if (native_pointer_p
3770 && !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->data_p, user_data_p))
3771 {
3772 return true;
3773 }
3774 }
3775
3776 iter_cp = iter_p->gc_next_cp;
3777 }
3778
3779 return false;
3780} /* jerry_objects_foreach_by_native_info */
3781
3782/**
3783 * Get native pointer and its type information, associated with the given native type info.
3784 *
3785 * Note:
3786 * If native pointer is present, its type information is returned in out_native_pointer_p
3787 *
3788 * @return true - if there is an associated pointer,
3789 * false - otherwise
3790 */
3791bool
3792jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get native pointer from */
3793 void **out_native_pointer_p, /**< [out] native pointer */
3794 const jerry_object_native_info_t *native_info_p) /**< the type info
3795 * of the native pointer */
3796{
3797 jerry_assert_api_available ();
3798
3799 if (!ecma_is_value_object (obj_val))
3800 {
3801 return false;
3802 }
3803
3804 ecma_native_pointer_t *native_pointer_p;
3805 native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val), (void *) native_info_p);
3806
3807 if (native_pointer_p == NULL)
3808 {
3809 return false;
3810 }
3811
3812 if (out_native_pointer_p != NULL)
3813 {
3814 *out_native_pointer_p = native_pointer_p->data_p;
3815 }
3816
3817 return true;
3818} /* jerry_get_object_native_pointer */
3819
3820/**
3821 * Set native pointer and an optional type info for the specified object.
3822 *
3823 *
3824 * Note:
3825 * If native pointer was already set for the object, its value is updated.
3826 *
3827 * Note:
3828 * If a non-NULL free callback is specified in the native type info,
3829 * it will be called by the garbage collector when the object is freed.
3830 * Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
3831 * The type info always overwrites the previous value, so passing
3832 * a NULL value deletes the current type info.
3833 */
3834void
3835jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set native pointer in */
3836 void *native_pointer_p, /**< native pointer */
3837 const jerry_object_native_info_t *native_info_p) /**< object's native type info */
3838{
3839 jerry_assert_api_available ();
3840
3841 if (ecma_is_value_object (obj_val))
3842 {
3843 ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3844
3845 ecma_create_native_pointer_property (object_p, native_pointer_p, (void *) native_info_p);
3846 }
3847} /* jerry_set_object_native_pointer */
3848
3849/**
3850 * Delete the previously set native pointer by the native type info from the specified object.
3851 *
3852 * Note:
3853 * If the specified object has no matching native pointer for the given native type info
3854 * the function has no effect.
3855 *
3856 * Note:
3857 * This operation cannot throw an exception.
3858 *
3859 * @return true - if the native pointer has been deleted succesfully
3860 * false - otherwise
3861 */
3862bool
3863jerry_delete_object_native_pointer (const jerry_value_t obj_val, /**< object to delete native pointer from */
3864 const jerry_object_native_info_t *native_info_p) /**< object's native type info */
3865{
3866 jerry_assert_api_available ();
3867
3868 if (ecma_is_value_object (obj_val))
3869 {
3870 ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3871
3872 return ecma_delete_native_pointer_property (object_p, (void *) native_info_p);
3873 }
3874
3875 return false;
3876} /* jerry_delete_object_native_pointer */
3877
3878/**
3879 * Applies the given function to the every property in the object.
3880 *
3881 * @return true - if object fields traversal was performed successfully, i.e.:
3882 * - no unhandled exceptions were thrown in object fields traversal;
3883 * - object fields traversal was stopped on callback that returned false;
3884 * false - otherwise,
3885 * if getter of field threw a exception or unhandled exceptions were thrown during traversal;
3886 */
3887bool
3888jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */
3889 jerry_object_property_foreach_t foreach_p, /**< foreach function */
3890 void *user_data_p) /**< user data for foreach function */
3891{
3892 jerry_assert_api_available ();
3893
3894 if (!ecma_is_value_object (obj_val))
3895 {
3896 return false;
3897 }
3898
3899 ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3900 ecma_collection_t *names_p = ecma_op_object_enumerate (object_p);
3901
3902#if ENABLED (JERRY_BUILTIN_PROXY)
3903 if (names_p == NULL)
3904 {
3905 // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
3906 jcontext_release_exception ();
3907 return false;
3908 }
3909#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
3910
3911 ecma_value_t *buffer_p = names_p->buffer_p;
3912
3913 ecma_value_t property_value = ECMA_VALUE_EMPTY;
3914
3915 bool continuous = true;
3916
3917 for (uint32_t i = 0; continuous && (i < names_p->item_count); i++)
3918 {
3919 ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]);
3920
3921 property_value = ecma_op_object_get (object_p, property_name_p);
3922
3923 if (ECMA_IS_VALUE_ERROR (property_value))
3924 {
3925 break;
3926 }
3927
3928 continuous = foreach_p (buffer_p[i], property_value, user_data_p);
3929 ecma_free_value (property_value);
3930 }
3931
3932 ecma_collection_free (names_p);
3933
3934 if (!ECMA_IS_VALUE_ERROR (property_value))
3935 {
3936 return true;
3937 }
3938
3939 jcontext_release_exception ();
3940 return false;
3941} /* jerry_foreach_object_property */
3942
3943/**
3944 * Gets the property keys for the given object using the selected filters.
3945 *
3946 * @return array containing the filtered property keys in successful operation
3947 * value marked with error flag - otherwise
3948 */
3949jerry_value_t
3950jerry_object_get_property_names (const jerry_value_t obj_val, /**< object */
3951 jerry_property_filter_t filter) /**< property filter options */
3952{
3953 jerry_assert_api_available ();
3954
3955 if (!ecma_is_value_object (obj_val))
3956 {
3957 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3958 }
3959
3960 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
3961 ecma_object_t *obj_iter_p = obj_p;
3962 ecma_collection_t *result_p = ecma_new_collection ();
3963
3964 ecma_ref_object (obj_iter_p);
3965
3966 while (true)
3967 {
3968 /* Step 1. Get Object.[[OwnKeys]] */
3969 ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p);
3970
3971#if ENABLED (JERRY_BUILTIN_PROXY)
3972 if (prop_names_p == NULL)
3973 {
3974 ecma_deref_object (obj_iter_p);
3975 return jerry_throw (ECMA_VALUE_ERROR);
3976 }
3977#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
3978
3979 for (uint32_t i = 0; i < prop_names_p->item_count; i++)
3980 {
3981 ecma_value_t key = prop_names_p->buffer_p[i];
3982 ecma_string_t *key_p = ecma_get_prop_name_from_value (key);
3983 uint32_t index = ecma_string_get_array_index (key_p);
3984
3985 /* Step 2. Filter by key type */
3986 if (filter & (JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS
3987 | JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS
3988 | JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES))
3989 {
3990 if (ecma_is_value_symbol (key))
3991 {
3992 if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS)
3993 {
3994 continue;
3995 }
3996 }
3997 else if (index != ECMA_STRING_NOT_ARRAY_INDEX)
3998 {
3999 if ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)
4000 || ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)
4001 && !(filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER)))
4002 {
4003 continue;
4004 }
4005 }
4006 else if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)
4007 {
4008 continue;
4009 }
4010 }
4011
4012 /* Step 3. Filter property attributes */
4013 if (filter & (JERRY_PROPERTY_FILTER_EXLCUDE_NON_CONFIGURABLE
4014 | JERRY_PROPERTY_FILTER_EXLCUDE_NON_ENUMERABLE
4015 | JERRY_PROPERTY_FILTER_EXLCUDE_NON_WRITABLE))
4016 {
4017 ecma_property_descriptor_t prop_desc;
4018 ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_iter_p, key_p, &prop_desc);
4019
4020#if ENABLED (JERRY_BUILTIN_PROXY)
4021 if (ECMA_IS_VALUE_ERROR (status))
4022 {
4023 ecma_collection_free (prop_names_p);
4024 ecma_collection_free (result_p);
4025 ecma_deref_object (obj_iter_p);
4026 return jerry_throw (ECMA_VALUE_ERROR);
4027 }
4028#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
4029
4030 JERRY_ASSERT (ecma_is_value_true (status));
4031 uint16_t flags = prop_desc.flags;
4032 ecma_free_property_descriptor (&prop_desc);
4033
4034 if ((!(flags & ECMA_PROP_IS_CONFIGURABLE)
4035 && (filter & JERRY_PROPERTY_FILTER_EXLCUDE_NON_CONFIGURABLE))
4036 || (!(flags & ECMA_PROP_IS_ENUMERABLE)
4037 && (filter & JERRY_PROPERTY_FILTER_EXLCUDE_NON_ENUMERABLE))
4038 || (!(flags & ECMA_PROP_IS_WRITABLE)
4039 && (filter & JERRY_PROPERTY_FILTER_EXLCUDE_NON_WRITABLE)))
4040 {
4041 continue;
4042 }
4043 }
4044
4045 if (index != ECMA_STRING_NOT_ARRAY_INDEX
4046 && (filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER))
4047 {
4048 ecma_deref_ecma_string (key_p);
4049 key = ecma_make_uint32_value (index);
4050 }
4051 else
4052 {
4053 ecma_ref_ecma_string (key_p);
4054 }
4055
4056 if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) && obj_iter_p != obj_p)
4057 {
4058 uint32_t duplicate_idx = 0;
4059 while (duplicate_idx < result_p->item_count)
4060 {
4061 ecma_value_t value = result_p->buffer_p[duplicate_idx];
4062 JERRY_ASSERT (ecma_is_value_prop_name (value) || ecma_is_value_number (value));
4063 if (JERRY_UNLIKELY (ecma_is_value_number (value)))
4064 {
4065 if (ecma_get_number_from_value (value) == ecma_get_number_from_value (key))
4066 {
4067 break;
4068 }
4069 }
4070 else if (ecma_compare_ecma_strings (ecma_get_prop_name_from_value (value), key_p))
4071 {
4072 break;
4073 }
4074
4075 duplicate_idx++;
4076 }
4077
4078 if (duplicate_idx == result_p->item_count)
4079 {
4080 ecma_collection_push_back (result_p, key);
4081 }
4082 }
4083 else
4084 {
4085 ecma_collection_push_back (result_p, key);
4086 }
4087 }
4088
4089 ecma_collection_free (prop_names_p);
4090
4091 /* Step 4: Traverse prototype chain */
4092
4093 if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) != JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN)
4094 {
4095 break;
4096 }
4097
4098 ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_iter_p);
4099
4100 if (proto_p == NULL)
4101 {
4102 break;
4103 }
4104
4105 ecma_deref_object (obj_iter_p);
4106
4107 if (JERRY_UNLIKELY (proto_p == ECMA_OBJECT_POINTER_ERROR))
4108 {
4109 ecma_collection_free (result_p);
4110 return jerry_throw (ECMA_VALUE_ERROR);
4111 }
4112
4113 obj_iter_p = proto_p;
4114 }
4115
4116 ecma_deref_object (obj_iter_p);
4117
4118 return ecma_op_new_array_object_from_collection (result_p, false);
4119} /* jerry_object_get_property_names */
4120
4121/**
4122 * FromPropertyDescriptor abstract operation.
4123 *
4124 * @return new jerry_value_t - if success
4125 * value marked with error flag - otherwise
4126 */
4127jerry_value_t
4128jerry_from_property_descriptor (const jerry_property_descriptor_t *src_prop_desc_p) /**< property descriptor */
4129{
4130 jerry_assert_api_available ();
4131
4132 ecma_property_descriptor_t prop_desc = jerry_property_descriptor_to_ecma (src_prop_desc_p);
4133
4134 if (ECMA_IS_VALUE_ERROR (prop_desc.value))
4135 {
4136 return jerry_throw (prop_desc.value);
4137 }
4138
4139 ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc);
4140
4141 return ecma_make_object_value (desc_obj_p);
4142} /* jerry_from_property_descriptor */
4143
4144/**
4145 * ToPropertyDescriptor abstract operation.
4146 *
4147 * @return true - if the conversion is successful
4148 * thrown error - otherwise
4149 */
4150jerry_value_t
4151jerry_to_property_descriptor (jerry_value_t obj_value, /**< object value */
4152 jerry_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor
4153 * if return value is true,
4154 * unmodified otherwise */
4155{
4156 jerry_assert_api_available ();
4157
4158 ecma_property_descriptor_t prop_desc;
4159 jerry_value_t result = ecma_op_to_property_descriptor (obj_value, &prop_desc);
4160
4161 if (ECMA_IS_VALUE_ERROR (result))
4162 {
4163 return jerry_throw (result);
4164 }
4165
4166 JERRY_ASSERT (result == ECMA_VALUE_EMPTY);
4167
4168 *out_prop_desc_p = jerry_property_descriptor_from_ecma (&prop_desc);
4169 return ECMA_VALUE_TRUE;
4170} /* jerry_to_property_descriptor */
4171
4172/**
4173 * Resolve or reject the promise with an argument.
4174 *
4175 * @return undefined value - if success
4176 * value marked with error flag - otherwise
4177 */
4178jerry_value_t
4179jerry_resolve_or_reject_promise (jerry_value_t promise, /**< the promise value */
4180 jerry_value_t argument, /**< the argument */
4181 bool is_resolve) /**< whether the promise should be resolved or rejected */
4182{
4183 jerry_assert_api_available ();
4184
4185#if ENABLED (JERRY_BUILTIN_PROMISE)
4186 if (!ecma_is_value_object (promise) || !ecma_is_promise (ecma_get_object_from_value (promise)))
4187 {
4188 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
4189 }
4190
4191 if (ecma_is_value_error_reference (argument))
4192 {
4193 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4194 }
4195
4196 ecma_promise_object_t *promise_p = (ecma_promise_object_t *) ecma_get_object_from_value (promise);
4197 ecma_value_t function = is_resolve ? promise_p->resolve : promise_p->reject;
4198
4199 return ecma_op_function_call (ecma_get_object_from_value (function),
4200 ECMA_VALUE_UNDEFINED,
4201 &argument,
4202 1);
4203#else /* !ENABLED (JERRY_BUILTIN_PROMISE) */
4204 JERRY_UNUSED (promise);
4205 JERRY_UNUSED (argument);
4206 JERRY_UNUSED (is_resolve);
4207
4208 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
4209#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
4210} /* jerry_resolve_or_reject_promise */
4211
4212/**
4213 * Get the result of a promise.
4214 *
4215 * @return - Promise result
4216 * - Type error if the promise support was not enabled or the input was not a promise object
4217 */
4218jerry_value_t
4219jerry_get_promise_result (const jerry_value_t promise) /**< promise object to get the result from */
4220{
4221 jerry_assert_api_available ();
4222
4223#if ENABLED (JERRY_BUILTIN_PROMISE)
4224 if (!jerry_value_is_promise (promise))
4225 {
4226 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
4227 }
4228
4229 return ecma_promise_get_result (ecma_get_object_from_value (promise));
4230#else /* !ENABLED (JERRY_BUILTIN_PROMISE) */
4231 JERRY_UNUSED (promise);
4232 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
4233#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
4234} /* jerry_get_promise_result */
4235
4236/**
4237 * Get the state of a promise object.
4238 *
4239 * @return - the state of the promise (one of the jerry_promise_state_t enum values)
4240 * - JERRY_PROMISE_STATE_NONE is only returned if the input is not a promise object
4241 * or the promise support was not enabled.
4242 */
4243jerry_promise_state_t
4244jerry_get_promise_state (const jerry_value_t promise) /**< promise object to get the state from */
4245{
4246 jerry_assert_api_available ();
4247
4248#if ENABLED (JERRY_BUILTIN_PROMISE)
4249 if (!jerry_value_is_promise (promise))
4250 {
4251 return JERRY_PROMISE_STATE_NONE;
4252 }
4253
4254 uint16_t flags = ecma_promise_get_flags (ecma_get_object_from_value (promise));
4255 flags &= (ECMA_PROMISE_IS_PENDING | ECMA_PROMISE_IS_FULFILLED);
4256
4257 return (flags ? flags : JERRY_PROMISE_STATE_REJECTED);
4258#else /* !ENABLED (JERRY_BUILTIN_PROMISE) */
4259 JERRY_UNUSED (promise);
4260 return JERRY_PROMISE_STATE_NONE;
4261#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
4262} /* jerry_get_promise_state */
4263
4264/**
4265 * Get the well-knwon symbol represented by the given `symbol` enum value.
4266 *
4267 * Note:
4268 * returned value must be freed with jerry_release_value, when it is no longer needed.
4269 *
4270 * @return undefined value - if invalid well-known symbol was requested
4271 * well-known symbol value - otherwise
4272 */
4273jerry_value_t
4274jerry_get_well_known_symbol (jerry_well_known_symbol_t symbol) /**< jerry_well_known_symbol_t enum value */
4275{
4276 jerry_assert_api_available ();
4277
4278#if ENABLED (JERRY_ESNEXT)
4279 lit_magic_string_id_t id = (lit_magic_string_id_t) (LIT_GLOBAL_SYMBOL__FIRST + symbol);
4280
4281 if (!LIT_IS_GLOBAL_SYMBOL (id))
4282 {
4283 return ECMA_VALUE_UNDEFINED;
4284 }
4285
4286 return ecma_make_symbol_value (ecma_op_get_global_symbol (id));
4287#else /* !ENABLED (JERRY_ESNEXT) */
4288 JERRY_UNUSED (symbol);
4289
4290 return ECMA_VALUE_UNDEFINED;
4291#endif /* ENABLED (JERRY_ESNEXT) */
4292} /** jerry_get_well_known_symbol */
4293
4294/**
4295 * Returns the description internal property of a symbol.
4296 *
4297 * Note:
4298 * returned value must be freed with jerry_release_value, when it is no longer needed.
4299 *
4300 * @return string or undefined value containing the symbol's description - if success
4301 * thrown error - otherwise
4302 */
4303jerry_value_t
4304jerry_get_symbol_description (const jerry_value_t symbol) /**< symbol value */
4305{
4306 jerry_assert_api_available ();
4307
4308#if ENABLED (JERRY_ESNEXT)
4309 if (!ecma_is_value_symbol (symbol))
4310 {
4311 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
4312 }
4313
4314 /* Note: This operation cannot throw an error */
4315 return ecma_copy_value (ecma_get_symbol_description (ecma_get_symbol_from_value (symbol)));
4316#else /* !ENABLED (JERRY_ESNEXT) */
4317 JERRY_UNUSED (symbol);
4318
4319 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported.")));
4320#endif /* ENABLED (JERRY_ESNEXT) */
4321} /* jerry_get_symbol_description */
4322
4323/**
4324 * Call the SymbolDescriptiveString ecma builtin operation on the symbol value.
4325 *
4326 * Note:
4327 * returned value must be freed with jerry_release_value, when it is no longer needed.
4328 *
4329 * @return string value containing the symbol's descriptive string - if success
4330 * thrown error - otherwise
4331 */
4332jerry_value_t
4333jerry_get_symbol_descriptive_string (const jerry_value_t symbol) /**< symbol value */
4334{
4335 jerry_assert_api_available ();
4336
4337#if ENABLED (JERRY_ESNEXT)
4338 if (!ecma_is_value_symbol (symbol))
4339 {
4340 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
4341 }
4342
4343 /* Note: This operation cannot throw an error */
4344 return ecma_get_symbol_descriptive_string (symbol);
4345#else /* !ENABLED (JERRY_ESNEXT) */
4346 JERRY_UNUSED (symbol);
4347
4348 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported.")));
4349#endif /* ENABLED (JERRY_ESNEXT) */
4350} /** jerry_get_symbol_descriptive_string */
4351
4352/**
4353 * Get the number of uint64 digits of a BigInt value
4354 *
4355 * @return number of uint64 digits
4356 */
4357uint32_t
4358jerry_get_bigint_size_in_digits (jerry_value_t value) /**< BigInt value */
4359{
4360 jerry_assert_api_available ();
4361
4362#if ENABLED (JERRY_BUILTIN_BIGINT)
4363 if (!ecma_is_value_bigint (value))
4364 {
4365 return 0;
4366 }
4367
4368 return ecma_bigint_get_size_in_digits (value);
4369#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
4370 JERRY_UNUSED (value);
4371 return 0;
4372#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
4373} /* jerry_get_bigint_size_in_digits */
4374
4375/**
4376 * Get the uint64 digits of a BigInt value (lowest digit first)
4377 */
4378void
4379jerry_get_bigint_digits (jerry_value_t value, /**< BigInt value */
4380 uint64_t *digits_p, /**< [out] buffer for digits */
4381 uint32_t size, /**< buffer size in digits */
4382 bool *sign_p) /**< [out] sign of BigInt */
4383{
4384#if ENABLED (JERRY_BUILTIN_BIGINT)
4385 if (!ecma_is_value_bigint (value))
4386 {
4387 if (sign_p != NULL)
4388 {
4389 *sign_p = false;
4390 }
4391 memset (digits_p, 0, size * sizeof (uint64_t));
4392 }
4393
4394 ecma_bigint_get_digits_and_sign (value, digits_p, size, sign_p);
4395#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
4396 JERRY_UNUSED (value);
4397
4398 if (sign_p != NULL)
4399 {
4400 *sign_p = false;
4401 }
4402 memset (digits_p, 0, size * sizeof (uint64_t));
4403#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
4404} /* jerry_get_bigint_digits */
4405
4406/**
4407 * Get the target object of a Proxy object
4408 *
4409 * @return type error - if proxy_value is not a Proxy object
4410 * target object - otherwise
4411 */
4412jerry_value_t
4413jerry_get_proxy_target (jerry_value_t proxy_value) /**< proxy value */
4414{
4415 jerry_assert_api_available ();
4416
4417#if ENABLED (JERRY_BUILTIN_PROXY)
4418 if (ecma_is_value_object (proxy_value))
4419 {
4420 ecma_object_t *object_p = ecma_get_object_from_value (proxy_value);
4421
4422 if (ECMA_OBJECT_IS_PROXY (object_p))
4423 {
4424 ecma_proxy_object_t *proxy_object_p = (ecma_proxy_object_t *) object_p;
4425
4426 if (!ecma_is_value_null (proxy_object_p->target))
4427 {
4428 ecma_ref_object (ecma_get_object_from_value (proxy_object_p->target));
4429 }
4430 return proxy_object_p->target;
4431 }
4432 }
4433#else /* !ENABLED (JERRY_BUILTIN_PROXY) */
4434 JERRY_UNUSED (proxy_value);
4435#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
4436
4437 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Passed value is not a proxy object")));
4438} /* jerry_get_proxy_target */
4439
4440/**
4441 * Validate UTF-8 string
4442 *
4443 * @return true - if UTF-8 string is well-formed
4444 * false - otherwise
4445 */
4446bool
4447jerry_is_valid_utf8_string (const jerry_char_t *utf8_buf_p, /**< UTF-8 string */
4448 jerry_size_t buf_size) /**< string size */
4449{
4450 return lit_is_valid_utf8_string ((lit_utf8_byte_t *) utf8_buf_p,
4451 (lit_utf8_size_t) buf_size);
4452} /* jerry_is_valid_utf8_string */
4453
4454/**
4455 * Validate CESU-8 string
4456 *
4457 * @return true - if CESU-8 string is well-formed
4458 * false - otherwise
4459 */
4460bool
4461jerry_is_valid_cesu8_string (const jerry_char_t *cesu8_buf_p, /**< CESU-8 string */
4462 jerry_size_t buf_size) /**< string size */
4463{
4464 return lit_is_valid_cesu8_string ((lit_utf8_byte_t *) cesu8_buf_p,
4465 (lit_utf8_size_t) buf_size);
4466} /* jerry_is_valid_cesu8_string */
4467
4468/**
4469 * Allocate memory on the engine's heap.
4470 *
4471 * Note:
4472 * This function may take away memory from the executed JavaScript code.
4473 * If any other dynamic memory allocation API is available (e.g., libc
4474 * malloc), it should be used instead.
4475 *
4476 * @return allocated memory on success
4477 * NULL otherwise
4478 */
4479void *
4480jerry_heap_alloc (size_t size) /**< size of the memory block */
4481{
4482 jerry_assert_api_available ();
4483
4484 return jmem_heap_alloc_block_null_on_error (size);
4485} /* jerry_heap_alloc */
4486
4487/**
4488 * Free memory allocated on the engine's heap.
4489 */
4490void
4491jerry_heap_free (void *mem_p, /**< value returned by jerry_heap_alloc */
4492 size_t size) /**< same size as passed to jerry_heap_alloc */
4493{
4494 jerry_assert_api_available ();
4495
4496 jmem_heap_free_block (mem_p, size);
4497} /* jerry_heap_free */
4498
4499/**
4500 * Create an external engine context.
4501 *
4502 * @return the pointer to the context.
4503 */
4504jerry_context_t *
4505jerry_create_context (uint32_t heap_size, /**< the size of heap */
4506 jerry_context_alloc_t alloc, /**< the alloc function */
4507 void *cb_data_p) /**< the cb_data for alloc function */
4508{
4509 JERRY_UNUSED (heap_size);
4510
4511#if ENABLED (JERRY_EXTERNAL_CONTEXT)
4512
4513 size_t total_size = sizeof (jerry_context_t) + JMEM_ALIGNMENT;
4514
4515#if !ENABLED (JERRY_SYSTEM_ALLOCATOR)
4516 heap_size = JERRY_ALIGNUP (heap_size, JMEM_ALIGNMENT);
4517
4518 /* Minimum heap size is 1Kbyte. */
4519 if (heap_size < 1024)
4520 {
4521 return NULL;
4522 }
4523
4524 total_size += heap_size;
4525#endif /* !ENABLED (JERRY_SYSTEM_ALLOCATOR) */
4526
4527 total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT);
4528
4529 jerry_context_t *context_p = (jerry_context_t *) alloc (total_size, cb_data_p);
4530
4531 if (context_p == NULL)
4532 {
4533 return NULL;
4534 }
4535
4536 memset (context_p, 0, total_size);
4537
4538 uintptr_t context_ptr = ((uintptr_t) context_p) + sizeof (jerry_context_t);
4539 context_ptr = JERRY_ALIGNUP (context_ptr, (uintptr_t) JMEM_ALIGNMENT);
4540
4541 uint8_t *byte_p = (uint8_t *) context_ptr;
4542
4543#if !ENABLED (JERRY_SYSTEM_ALLOCATOR)
4544 context_p->heap_p = (jmem_heap_t *) byte_p;
4545 context_p->heap_size = heap_size;
4546 byte_p += heap_size;
4547#endif /* !ENABLED (JERRY_SYSTEM_ALLOCATOR) */
4548
4549 JERRY_ASSERT (byte_p <= ((uint8_t *) context_p) + total_size);
4550
4551 JERRY_UNUSED (byte_p);
4552 return context_p;
4553
4554#else /* !ENABLED (JERRY_EXTERNAL_CONTEXT) */
4555
4556 JERRY_UNUSED (alloc);
4557 JERRY_UNUSED (cb_data_p);
4558
4559 return NULL;
4560
4561#endif /* ENABLED (JERRY_EXTERNAL_CONTEXT) */
4562} /* jerry_create_context */
4563
4564/**
4565 * If JERRY_VM_EXEC_STOP is enabled the callback passed to this function is
4566 * periodically called with the user_p argument. If frequency is greater
4567 * than 1, the callback is only called at every frequency ticks.
4568 */
4569void
4570jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< periodically called user function */
4571 void *user_p, /**< pointer passed to the function */
4572 uint32_t frequency) /**< frequency of the function call */
4573{
4574#if ENABLED (JERRY_VM_EXEC_STOP)
4575 if (frequency == 0)
4576 {
4577 frequency = 1;
4578 }
4579
4580 JERRY_CONTEXT (vm_exec_stop_frequency) = frequency;
4581 JERRY_CONTEXT (vm_exec_stop_counter) = frequency;
4582 JERRY_CONTEXT (vm_exec_stop_user_p) = user_p;
4583 JERRY_CONTEXT (vm_exec_stop_cb) = stop_cb;
4584#else /* !ENABLED (JERRY_VM_EXEC_STOP) */
4585 JERRY_UNUSED (stop_cb);
4586 JERRY_UNUSED (user_p);
4587 JERRY_UNUSED (frequency);
4588#endif /* ENABLED (JERRY_VM_EXEC_STOP) */
4589} /* jerry_set_vm_exec_stop_callback */
4590
4591/**
4592 * Get backtrace. The backtrace is an array of strings where
4593 * each string contains the position of the corresponding frame.
4594 * The array length is zero if the backtrace is not available.
4595 *
4596 * @return array value
4597 */
4598jerry_value_t
4599jerry_get_backtrace (uint32_t max_depth) /**< depth limit of the backtrace */
4600{
4601 return vm_get_backtrace (max_depth, NULL);
4602} /* jerry_get_backtrace */
4603
4604/**
4605 * Get backtrace. The backtrace is an array of strings where
4606 * each string contains the position of the corresponding frame.
4607 * The array length is zero if the backtrace is not available.
4608 *
4609 * @return array value
4610 */
4611jerry_value_t
4612jerry_get_backtrace_from (uint32_t max_depth, /**< depth limit of the backtrace */
4613 jerry_value_t ignored_function) /**< collect backtrace after this function */
4614{
4615 ecma_object_t *ignored_function_p = NULL;
4616
4617 if (ecma_is_value_object (ignored_function))
4618 {
4619 ignored_function_p = ecma_get_object_from_value (ignored_function);
4620
4621 while (true)
4622 {
4623 ecma_object_type_t type = ecma_get_object_type (ignored_function_p);
4624
4625 if (type == ECMA_OBJECT_TYPE_FUNCTION || type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION)
4626 {
4627 break;
4628 }
4629
4630 if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
4631 {
4632 ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) ignored_function_p;
4633 jmem_cpointer_tag_t target_function = bound_func_p->header.u.bound_function.target_function;
4634
4635 ignored_function_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, target_function);
4636 continue;
4637 }
4638
4639 ignored_function_p = NULL;
4640 break;
4641 }
4642 }
4643
4644 return vm_get_backtrace (max_depth, ignored_function_p);
4645} /* jerry_get_backtrace_from */
4646
4647/**
4648 * Get the resource name (usually a file name) of the currently executed script or the given function object
4649 *
4650 * Note: returned value must be freed with jerry_release_value, when it is no longer needed
4651 *
4652 * @return JS string constructed from
4653 * - the currently executed function object's resource name, if the given value is undefined
4654 * - resource name of the function object, if the given value is a function object
4655 * - "<anonymous>", otherwise
4656 */
4657jerry_value_t
4658jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */
4659{
4660#if ENABLED (JERRY_RESOURCE_NAME)
4661 if (ecma_is_value_undefined (value))
4662 {
4663 if (JERRY_CONTEXT (vm_top_context_p) != NULL)
4664 {
4665 return ecma_copy_value (ecma_get_resource_name (JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p));
4666 }
4667 }
4668 else if (ecma_is_value_object (value))
4669 {
4670 ecma_object_t *obj_p = ecma_get_object_from_value (value);
4671
4672 if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION
4673 && !ecma_get_object_is_builtin (obj_p))
4674 {
4675 ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p;
4676
4677 const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
4678
4679 return ecma_copy_value (ecma_get_resource_name (bytecode_data_p));
4680 }
4681 }
4682#endif /* ENABLED (JERRY_RESOURCE_NAME) */
4683
4684 JERRY_UNUSED (value);
4685 return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
4686} /* jerry_get_resource_name */
4687
4688/**
4689 * Access the "new.target" value.
4690 *
4691 * The "new.target" value depends on the current call site. That is
4692 * this method will only have a function object result if, at the call site
4693 * it was called inside a constructor method invoked with "new".
4694 *
4695 * @return "undefined" - if at the call site it was not a constructor call.
4696 * function object - if the current call site is in a constructor call.
4697 */
4698jerry_value_t
4699jerry_get_new_target (void)
4700{
4701#if ENABLED (JERRY_ESNEXT)
4702 ecma_object_t *current_new_target_p = JERRY_CONTEXT (current_new_target_p);
4703
4704 if (current_new_target_p == NULL)
4705 {
4706 return jerry_create_undefined ();
4707 }
4708
4709 ecma_ref_object (current_new_target_p);
4710 return ecma_make_object_value (current_new_target_p);
4711#else /* !ENABLED (JERRY_ESNEXT) */
4712 return jerry_create_undefined ();
4713#endif /* ENABLED (JERRY_ESNEXT) */
4714} /* jerry_get_new_target */
4715
4716/**
4717 * Replaces the currently active realm with another realm.
4718 *
4719 * The replacement should be temporary, and the original realm must be
4720 * restored after the tasks are completed. During the replacement, the
4721 * realm must be referenced by the application (i.e. the gc must not
4722 * reclaim it). This is also true to the returned previously active
4723 * realm, so there is no need to free the value after the restoration.
4724 *
4725 * @return previous realm value - if the passed value is a realm
4726 * exception - otherwise
4727 */
4728jerry_value_t
4729jerry_set_realm (jerry_value_t realm_value) /**< jerry api value */
4730{
4731 jerry_assert_api_available ();
4732
4733#if ENABLED (JERRY_BUILTIN_REALMS)
4734 if (ecma_is_value_object (realm_value))
4735 {
4736 ecma_object_t *object_p = ecma_get_object_from_value (realm_value);
4737
4738 if (ecma_get_object_is_builtin (object_p)
4739 && ecma_builtin_is_global (object_p))
4740 {
4741 ecma_global_object_t *previous_global_object_p = JERRY_CONTEXT (global_object_p);
4742 JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) object_p;
4743 return ecma_make_object_value ((ecma_object_t *) previous_global_object_p);
4744 }
4745 }
4746
4747 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Passed argument is not a realm")));
4748#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
4749 JERRY_UNUSED (realm_value);
4750 return jerry_throw (ecma_raise_reference_error (ECMA_ERR_MSG ("Realm is not available")));
4751#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
4752} /* jerry_set_realm */
4753
4754/**
4755 * Gets the 'this' binding of a realm
4756 *
4757 * @return type error - if realm_value is not a realm
4758 * this value - otherwise
4759 */
4760jerry_value_t
4761jerry_realm_get_this (jerry_value_t realm_value) /**< realm value */
4762{
4763 jerry_assert_api_available ();
4764
4765#if ENABLED (JERRY_BUILTIN_REALMS)
4766 if (ecma_is_value_object (realm_value))
4767 {
4768 ecma_object_t *object_p = ecma_get_object_from_value (realm_value);
4769
4770 if (ecma_get_object_is_builtin (object_p)
4771 && ecma_builtin_is_global (object_p))
4772 {
4773 ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p;
4774
4775 ecma_ref_object (ecma_get_object_from_value (global_object_p->this_binding));
4776 return global_object_p->this_binding;
4777 }
4778 }
4779
4780#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
4781 ecma_object_t *global_object_p = ecma_builtin_get_global ();
4782
4783 if (realm_value == ecma_make_object_value (global_object_p))
4784 {
4785 ecma_ref_object (global_object_p);
4786 return realm_value;
4787 }
4788#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
4789
4790 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Passed argument is not a realm")));
4791} /* jerry_realm_get_this */
4792
4793/**
4794 * Sets the 'this' binding of a realm
4795 *
4796 * This function must be called before executing any script on the realm.
4797 * Otherwise the operation is undefined.
4798 *
4799 * @return type error - if realm_value is not a realm or this_value is not object
4800 * true - otherwise
4801 */
4802jerry_value_t
4803jerry_realm_set_this (jerry_value_t realm_value, /**< realm value */
4804 jerry_value_t this_value) /**< this value */
4805{
4806 jerry_assert_api_available ();
4807
4808#if ENABLED (JERRY_BUILTIN_REALMS)
4809 if (!ecma_is_value_object (this_value))
4810 {
4811 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Second argument must be an object")));
4812 }
4813
4814 if (ecma_is_value_object (realm_value))
4815 {
4816 ecma_object_t *object_p = ecma_get_object_from_value (realm_value);
4817
4818 if (ecma_get_object_is_builtin (object_p)
4819 && ecma_builtin_is_global (object_p))
4820 {
4821 ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p;
4822 global_object_p->this_binding = this_value;
4823
4824 ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL,
4825 ecma_get_object_from_value (this_value),
4826 ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
4827
4828 ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p);
4829#if ENABLED (JERRY_ESNEXT)
4830 global_object_p->global_scope_cp = global_object_p->global_env_cp;
4831#endif /* ENABLED (JERRY_ESNEXT) */
4832 ecma_deref_object (global_lex_env_p);
4833 return ECMA_VALUE_TRUE;
4834 }
4835 }
4836
4837 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("First argument is not a realm")));
4838#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
4839 JERRY_UNUSED (realm_value);
4840 JERRY_UNUSED (this_value);
4841 return jerry_throw (ecma_raise_reference_error (ECMA_ERR_MSG ("Realm is not available")));
4842#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
4843} /* jerry_realm_set_this */
4844
4845/**
4846 * Check if the given value is an ArrayBuffer object.
4847 *
4848 * @return true - if it is an ArrayBuffer object
4849 * false - otherwise
4850 */
4851bool
4852jerry_value_is_arraybuffer (const jerry_value_t value) /**< value to check if it is an ArrayBuffer */
4853{
4854 jerry_assert_api_available ();
4855
4856#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
4857 return ecma_is_arraybuffer (value);
4858#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4859 JERRY_UNUSED (value);
4860 return false;
4861#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4862} /* jerry_value_is_arraybuffer */
4863
4864/**
4865 * Creates an ArrayBuffer object with the given length (size).
4866 *
4867 * Notes:
4868 * * the length is specified in bytes.
4869 * * returned value must be freed with jerry_release_value, when it is no longer needed.
4870 * * if the typed arrays are disabled this will return a TypeError.
4871 *
4872 * @return value of the constructed ArrayBuffer object
4873 */
4874jerry_value_t
4875jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffer to create */
4876{
4877 jerry_assert_api_available ();
4878
4879#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
4880 return jerry_return (ecma_make_object_value (ecma_arraybuffer_new_object (size)));
4881#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4882 JERRY_UNUSED (size);
4883 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
4884#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4885} /* jerry_create_arraybuffer */
4886
4887/**
4888 * Creates an ArrayBuffer object with user specified buffer.
4889 *
4890 * Notes:
4891 * * the size is specified in bytes.
4892 * * the buffer passed should be at least the specified bytes big.
4893 * * if the typed arrays are disabled this will return a TypeError.
4894 * * if the size is zero or buffer_p is a null pointer this will return an empty ArrayBuffer.
4895 *
4896 * @return value of the construced ArrayBuffer object
4897 */
4898jerry_value_t
4899jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the buffer to used */
4900 uint8_t *buffer_p, /**< buffer to use as the ArrayBuffer's backing */
4901 jerry_object_native_free_callback_t free_cb) /**< buffer free callback */
4902{
4903 jerry_assert_api_available ();
4904
4905#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
4906 ecma_object_t *arraybuffer;
4907
4908 if (JERRY_UNLIKELY (size == 0 || buffer_p == NULL))
4909 {
4910 arraybuffer = ecma_arraybuffer_new_object (0);
4911 }
4912 else
4913 {
4914 arraybuffer = ecma_arraybuffer_new_object_external (size,
4915 buffer_p,
4916 (ecma_object_native_free_callback_t) free_cb);
4917 }
4918
4919 return jerry_return (ecma_make_object_value (arraybuffer));
4920#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4921 JERRY_UNUSED (size);
4922 JERRY_UNUSED (buffer_p);
4923 JERRY_UNUSED (free_cb);
4924 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
4925#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4926} /* jerry_create_arraybuffer_external */
4927
4928/**
4929 * Copy bytes into the ArrayBuffer from a buffer.
4930 *
4931 * Note:
4932 * * if the object passed is not an ArrayBuffer will return 0.
4933 *
4934 * @return number of bytes copied into the ArrayBuffer.
4935 */
4936jerry_length_t
4937jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer */
4938 jerry_length_t offset, /**< start offset of the ArrayBuffer */
4939 const uint8_t *buf_p, /**< buffer to copy from */
4940 jerry_length_t buf_size) /**< number of bytes to copy from the buffer */
4941{
4942 jerry_assert_api_available ();
4943
4944#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
4945 if (!ecma_is_arraybuffer (value))
4946 {
4947 return 0;
4948 }
4949
4950 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
4951 jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
4952
4953 if (offset >= length)
4954 {
4955 return 0;
4956 }
4957
4958 jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size);
4959
4960 if (copy_count > 0)
4961 {
4962 lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
4963
4964 memcpy ((void *) (mem_buffer_p + offset), (void *) buf_p, copy_count);
4965 }
4966
4967 return copy_count;
4968#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4969 JERRY_UNUSED (value);
4970 JERRY_UNUSED (offset);
4971 JERRY_UNUSED (buf_p);
4972 JERRY_UNUSED (buf_size);
4973 return 0;
4974#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
4975} /* jerry_arraybuffer_write */
4976
4977/**
4978 * Copy bytes from a buffer into an ArrayBuffer.
4979 *
4980 * Note:
4981 * * if the object passed is not an ArrayBuffer will return 0.
4982 *
4983 * @return number of bytes read from the ArrayBuffer.
4984 */
4985jerry_length_t
4986jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer to read from */
4987 jerry_length_t offset, /**< start offset of the ArrayBuffer */
4988 uint8_t *buf_p, /**< destination buffer to copy to */
4989 jerry_length_t buf_size) /**< number of bytes to copy into the buffer */
4990{
4991 jerry_assert_api_available ();
4992
4993#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
4994 if (!ecma_is_arraybuffer (value))
4995 {
4996 return 0;
4997 }
4998
4999 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
5000 jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
5001
5002 if (offset >= length)
5003 {
5004 return 0;
5005 }
5006
5007 jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size);
5008
5009 if (copy_count > 0)
5010 {
5011 lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
5012
5013 memcpy ((void *) buf_p, (void *) (mem_buffer_p + offset), copy_count);
5014 }
5015
5016 return copy_count;
5017#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5018 JERRY_UNUSED (value);
5019 JERRY_UNUSED (offset);
5020 JERRY_UNUSED (buf_p);
5021 JERRY_UNUSED (buf_size);
5022 return 0;
5023#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5024} /* jerry_arraybuffer_read */
5025
5026/**
5027 * Get the length (size) of the ArrayBuffer in bytes.
5028 *
5029 * Note:
5030 * This is the 'byteLength' property of an ArrayBuffer.
5031 *
5032 * @return the length of the ArrayBuffer in bytes.
5033 */
5034jerry_length_t
5035jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer */
5036{
5037 jerry_assert_api_available ();
5038
5039#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5040 if (ecma_is_arraybuffer (value))
5041 {
5042 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
5043 return ecma_arraybuffer_get_length (buffer_p);
5044 }
5045#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5046 JERRY_UNUSED (value);
5047#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5048 return 0;
5049} /* jerry_get_arraybuffer_byte_length */
5050
5051/**
5052 * Get a pointer for the start of the ArrayBuffer.
5053 *
5054 * Note:
5055 * * This is a high-risk operation as the bounds are not checked
5056 * when accessing the pointer elements.
5057 *
5058 * @return pointer to the back-buffer of the ArrayBuffer.
5059 * pointer is NULL if:
5060 * - the parameter is not an ArrayBuffer
5061 * - an external ArrayBuffer has been detached
5062 */
5063uint8_t *
5064jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buffer to use */
5065{
5066 jerry_assert_api_available ();
5067
5068#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5069 if (ecma_is_value_error_reference (array_buffer)
5070 || !ecma_is_arraybuffer (array_buffer))
5071 {
5072 return NULL;
5073 }
5074
5075 ecma_object_t *buffer_p = ecma_get_object_from_value (array_buffer);
5076 lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
5077 return (uint8_t *const) mem_buffer_p;
5078#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5079 JERRY_UNUSED (array_buffer);
5080#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5081
5082 return NULL;
5083} /* jerry_get_arraybuffer_pointer */
5084
5085/**
5086 * Get if the ArrayBuffer is detachable.
5087 *
5088 * @return boolean value - if success
5089 * value marked with error flag - otherwise
5090 */
5091jerry_value_t
5092jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
5093{
5094 jerry_assert_api_available ();
5095
5096#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5097 if (ecma_is_arraybuffer (value))
5098 {
5099 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
5100 return ecma_arraybuffer_is_detached (buffer_p) ? ECMA_VALUE_FALSE : ECMA_VALUE_TRUE;
5101 }
5102#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5103 JERRY_UNUSED (value);
5104#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5105 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expected an ArrayBuffer")));
5106} /* jerry_is_arraybuffer_detachable */
5107
5108/**
5109 * Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
5110 *
5111 * Note: If the ArrayBuffer has been created with `jerry_create_arraybuffer_external`
5112 * the optional free callback is called on a successful detach operation
5113 *
5114 * @return null value - if success
5115 * value marked with error flag - otherwise
5116 */
5117jerry_value_t
5118jerry_detach_arraybuffer (const jerry_value_t value) /**< ArrayBuffer */
5119{
5120 jerry_assert_api_available ();
5121
5122#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5123 if (ecma_is_arraybuffer (value))
5124 {
5125 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
5126 if (ecma_arraybuffer_detach (buffer_p))
5127 {
5128 return ECMA_VALUE_NULL;
5129 }
5130 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has already been detached.")));
5131 }
5132#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5133 JERRY_UNUSED (value);
5134#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5135 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expected an ArrayBuffer")));
5136} /* jerry_detach_arraybuffer */
5137
5138/**
5139 * DataView related functions
5140 */
5141
5142/**
5143 * Creates a DataView object with the given ArrayBuffer, ByteOffset and ByteLength arguments.
5144 *
5145 * Notes:
5146 * * returned value must be freed with jerry_release_value, when it is no longer needed.
5147 * * if the DataView bulitin is disabled this will return a TypeError.
5148 *
5149 * @return value of the constructed DataView object - if success
5150 * created error - otherwise
5151 */
5152jerry_value_t
5153jerry_create_dataview (const jerry_value_t array_buffer, /**< arraybuffer to create DataView from */
5154 const jerry_length_t byte_offset, /**< offset in bytes, to the first byte in the buffer */
5155 const jerry_length_t byte_length) /**< number of elements in the byte array */
5156{
5157 jerry_assert_api_available ();
5158
5159#if ENABLED (JERRY_BUILTIN_DATAVIEW)
5160 if (ecma_is_value_error_reference (array_buffer))
5161 {
5162 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
5163 }
5164
5165 ecma_value_t arguments_p[3] =
5166 {
5167 array_buffer,
5168 ecma_make_uint32_value (byte_offset),
5169 ecma_make_uint32_value (byte_length)
5170 };
5171 ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p);
5172 if (old_new_target_p == NULL)
5173 {
5174 JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ECMA_BUILTIN_ID_DATAVIEW);
5175 }
5176
5177 ecma_value_t dataview_value = ecma_op_dataview_create (arguments_p, 3);
5178 JERRY_CONTEXT (current_new_target_p) = old_new_target_p;
5179 return jerry_return (dataview_value);
5180#else /* !ENABLED (JERRY_BUILTIN_DATAVIEW) */
5181 JERRY_UNUSED (array_buffer);
5182 JERRY_UNUSED (byte_offset);
5183 JERRY_UNUSED (byte_length);
5184 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported.")));
5185#endif /* ENABLED (JERRY_BUILTIN_DATAVIEW */
5186} /* jerry_create_dataview */
5187
5188/**
5189 * Check if the given value is a DataView object.
5190 *
5191 * @return true - if it is a DataView object
5192 * false - otherwise
5193 */
5194bool
5195jerry_value_is_dataview (const jerry_value_t value) /**< value to check if it is a DataView object */
5196{
5197 jerry_assert_api_available ();
5198
5199#if ENABLED (JERRY_BUILTIN_DATAVIEW)
5200 return ecma_is_dataview (value);
5201#else /* !ENABLED (JERRY_BUILTIN_DATAVIEW) */
5202 JERRY_UNUSED (value);
5203 return false;
5204#endif /* ENABLED (JERRY_BUILTIN_DATAVIEW */
5205} /* jerry_value_is_dataview */
5206
5207/**
5208 * Get the underlying ArrayBuffer from a DataView.
5209 *
5210 * Additionally the byteLength and byteOffset properties are also returned
5211 * which were specified when the DataView was created.
5212 *
5213 * Note:
5214 * the returned value must be freed with a jerry_release_value call
5215 *
5216 * @return ArrayBuffer of a DataView
5217 * TypeError if the object is not a DataView.
5218 */
5219jerry_value_t
5220jerry_get_dataview_buffer (const jerry_value_t value, /**< DataView to get the arraybuffer from */
5221 jerry_length_t *byte_offset, /**< [out] byteOffset property */
5222 jerry_length_t *byte_length) /**< [out] byteLength property */
5223{
5224 jerry_assert_api_available ();
5225
5226#if ENABLED (JERRY_BUILTIN_DATAVIEW)
5227 if (ecma_is_value_error_reference (value))
5228 {
5229 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
5230 }
5231
5232 ecma_dataview_object_t *dataview_p = ecma_op_dataview_get_object (value);
5233
5234 if (JERRY_UNLIKELY (dataview_p == NULL))
5235 {
5236 return ecma_create_error_reference_from_context ();
5237 }
5238
5239 if (byte_offset != NULL)
5240 {
5241 *byte_offset = dataview_p->byte_offset;
5242 }
5243
5244 if (byte_length != NULL)
5245 {
5246 *byte_length = dataview_p->header.u.class_prop.u.length;
5247 }
5248
5249 ecma_object_t *arraybuffer_p = dataview_p->buffer_p;
5250 ecma_ref_object (arraybuffer_p);
5251
5252 return ecma_make_object_value (arraybuffer_p);
5253#else /* !ENABLED (JERRY_BUILTIN_DATAVIEW) */
5254 JERRY_UNUSED (value);
5255 JERRY_UNUSED (byte_offset);
5256 JERRY_UNUSED (byte_length);
5257 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported.")));
5258#endif /* ENABLED (JERRY_BUILTIN_DATAVIEW */
5259} /* jerry_get_dataview_buffer */
5260
5261/**
5262 * TypedArray related functions
5263 */
5264
5265/**
5266 * Check if the given value is a TypedArray object.
5267 *
5268 * @return true - if it is a TypedArray object
5269 * false - otherwise
5270 */
5271bool
5272jerry_value_is_typedarray (jerry_value_t value) /**< value to check if it is a TypedArray */
5273{
5274 jerry_assert_api_available ();
5275
5276#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5277 return ecma_is_typedarray (value);
5278#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5279 JERRY_UNUSED (value);
5280 return false;
5281#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5282} /* jerry_value_is_typedarray */
5283
5284#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5285/**
5286 * TypedArray mapping type
5287 */
5288typedef struct
5289{
5290 jerry_typedarray_type_t api_type; /**< api type */
5291 ecma_builtin_id_t prototype_id; /**< prototype ID */
5292 ecma_typedarray_type_t id; /**< typedArray ID */
5293 uint8_t element_size_shift; /**< element size shift */
5294} jerry_typedarray_mapping_t;
5295
5296/**
5297 * List of TypedArray mappings
5298 */
5299static jerry_typedarray_mapping_t jerry_typedarray_mappings[] =
5300{
5301#define TYPEDARRAY_ENTRY(NAME, LIT_NAME, SIZE_SHIFT) \
5302 { JERRY_TYPEDARRAY_ ## NAME, ECMA_BUILTIN_ID_ ## NAME ## ARRAY_PROTOTYPE, \
5303 ECMA_ ## LIT_NAME ## _ARRAY, SIZE_SHIFT }
5304
5305 TYPEDARRAY_ENTRY (UINT8, UINT8, 0),
5306 TYPEDARRAY_ENTRY (UINT8CLAMPED, UINT8_CLAMPED, 0),
5307 TYPEDARRAY_ENTRY (INT8, INT8, 0),
5308 TYPEDARRAY_ENTRY (UINT16, UINT16, 1),
5309 TYPEDARRAY_ENTRY (INT16, INT16, 1),
5310 TYPEDARRAY_ENTRY (UINT32, UINT32, 2),
5311 TYPEDARRAY_ENTRY (INT32, INT32, 2),
5312 TYPEDARRAY_ENTRY (FLOAT32, FLOAT32, 2),
5313#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
5314 TYPEDARRAY_ENTRY (FLOAT64, FLOAT64, 3),
5315#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
5316#if ENABLED (JERRY_BUILTIN_BIGINT)
5317 TYPEDARRAY_ENTRY (BIGINT64, BIGINT64, 3),
5318 TYPEDARRAY_ENTRY (BIGUINT64, BIGUINT64, 3),
5319#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
5320#undef TYPEDARRAY_ENTRY
5321};
5322
5323/**
5324 * Helper function to get the TypedArray prototype, typedArray id, and element size shift
5325 * information.
5326 *
5327 * @return true - if the TypedArray information was found
5328 * false - if there is no such TypedArray type
5329 */
5330static bool
5331jerry_typedarray_find_by_type (jerry_typedarray_type_t type_name, /**< type of the TypedArray */
5332 ecma_builtin_id_t *prototype_id, /**< [out] found prototype object id */
5333 ecma_typedarray_type_t *id, /**< [out] found typedArray id */
5334 uint8_t *element_size_shift) /**< [out] found element size shift value */
5335{
5336 JERRY_ASSERT (prototype_id != NULL);
5337 JERRY_ASSERT (id != NULL);
5338 JERRY_ASSERT (element_size_shift != NULL);
5339
5340 for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
5341 {
5342 if (type_name == jerry_typedarray_mappings[i].api_type)
5343 {
5344 *prototype_id = jerry_typedarray_mappings[i].prototype_id;
5345 *id = jerry_typedarray_mappings[i].id;
5346 *element_size_shift = jerry_typedarray_mappings[i].element_size_shift;
5347 return true;
5348 }
5349 }
5350
5351 return false;
5352} /* jerry_typedarray_find_by_type */
5353
5354#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5355
5356/**
5357 * Create a TypedArray object with a given type and length.
5358 *
5359 * Notes:
5360 * * returns TypeError if an incorrect type (type_name) is specified.
5361 * * byteOffset property will be set to 0.
5362 * * byteLength property will be a multiple of the length parameter (based on the type).
5363 *
5364 * @return - new TypedArray object
5365 */
5366jerry_value_t
5367jerry_create_typedarray (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
5368 jerry_length_t length) /**< element count of the new TypedArray */
5369{
5370 jerry_assert_api_available ();
5371
5372#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5373 ecma_builtin_id_t prototype_id = 0;
5374 ecma_typedarray_type_t id = 0;
5375 uint8_t element_size_shift = 0;
5376
5377 if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift))
5378 {
5379 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
5380 }
5381
5382 ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
5383
5384 ecma_value_t array_value = ecma_typedarray_create_object_with_length (length,
5385 NULL,
5386 prototype_obj_p,
5387 element_size_shift,
5388 id);
5389
5390 JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value));
5391
5392 return array_value;
5393#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5394 JERRY_UNUSED (type_name);
5395 JERRY_UNUSED (length);
5396 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
5397#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5398} /* jerry_create_typedarray */
5399
5400/**
5401 * Create a TypedArray object using the given arraybuffer and size information.
5402 *
5403 * Notes:
5404 * * returns TypeError if an incorrect type (type_name) is specified.
5405 * * this is the 'new %TypedArray%(arraybuffer, byteOffset, length)' equivalent call.
5406 *
5407 * @return - new TypedArray object
5408 */
5409jerry_value_t
5410jerry_create_typedarray_for_arraybuffer_sz (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
5411 const jerry_value_t arraybuffer, /**< ArrayBuffer to use */
5412 jerry_length_t byte_offset, /**< offset for the ArrayBuffer */
5413 jerry_length_t length) /**< number of elements to use from ArrayBuffer */
5414{
5415 jerry_assert_api_available ();
5416
5417#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5418 if (ecma_is_value_error_reference (arraybuffer))
5419 {
5420 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
5421 }
5422
5423 ecma_builtin_id_t prototype_id = 0;
5424 ecma_typedarray_type_t id = 0;
5425 uint8_t element_size_shift = 0;
5426
5427 if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift))
5428 {
5429 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
5430 }
5431
5432 if (!ecma_is_arraybuffer (arraybuffer))
5433 {
5434 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an ArrayBuffer")));
5435 }
5436
5437 ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
5438 ecma_value_t arguments_p[3] =
5439 {
5440 arraybuffer,
5441 ecma_make_uint32_value (byte_offset),
5442 ecma_make_uint32_value (length)
5443 };
5444
5445 ecma_value_t array_value = ecma_op_create_typedarray (arguments_p, 3, prototype_obj_p, element_size_shift, id);
5446 ecma_free_value (arguments_p[1]);
5447 ecma_free_value (arguments_p[2]);
5448
5449 return jerry_return (array_value);
5450#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5451 JERRY_UNUSED (type_name);
5452 JERRY_UNUSED (arraybuffer);
5453 JERRY_UNUSED (byte_offset);
5454 JERRY_UNUSED (length);
5455 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
5456#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5457} /* jerry_create_typedarray_for_arraybuffer_sz */
5458
5459/**
5460 * Create a TypedArray object using the given arraybuffer and size information.
5461 *
5462 * Notes:
5463 * * returns TypeError if an incorrect type (type_name) is specified.
5464 * * this is the 'new %TypedArray%(arraybuffer)' equivalent call.
5465 *
5466 * @return - new TypedArray object
5467 */
5468jerry_value_t
5469jerry_create_typedarray_for_arraybuffer (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
5470 const jerry_value_t arraybuffer) /**< ArrayBuffer to use */
5471{
5472 jerry_assert_api_available ();
5473
5474#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5475 if (ecma_is_value_error_reference (arraybuffer))
5476 {
5477 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
5478 }
5479
5480 jerry_length_t byteLength = jerry_get_arraybuffer_byte_length (arraybuffer);
5481 return jerry_create_typedarray_for_arraybuffer_sz (type_name, arraybuffer, 0, byteLength);
5482#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5483 JERRY_UNUSED (type_name);
5484 JERRY_UNUSED (arraybuffer);
5485 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
5486#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5487} /* jerry_create_typedarray_for_arraybuffer */
5488
5489/**
5490 * Get the type of the TypedArray.
5491 *
5492 * @return - type of the TypedArray
5493 * - JERRY_TYPEDARRAY_INVALID if the argument is not a TypedArray
5494 */
5495jerry_typedarray_type_t
5496jerry_get_typedarray_type (jerry_value_t value) /**< object to get the TypedArray type */
5497{
5498 jerry_assert_api_available ();
5499
5500#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5501 if (!ecma_is_typedarray (value))
5502 {
5503 return JERRY_TYPEDARRAY_INVALID;
5504 }
5505
5506 ecma_object_t *array_p = ecma_get_object_from_value (value);
5507 ecma_typedarray_type_t class_type = ecma_get_typedarray_id (array_p);
5508
5509 for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
5510 {
5511 if (class_type == jerry_typedarray_mappings[i].id)
5512 {
5513 return jerry_typedarray_mappings[i].api_type;
5514 }
5515 }
5516#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5517 JERRY_UNUSED (value);
5518#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5519
5520 return JERRY_TYPEDARRAY_INVALID;
5521} /* jerry_get_typedarray_type */
5522
5523/**
5524 * Get the element count of the TypedArray.
5525 *
5526 * @return length of the TypedArray.
5527 */
5528jerry_length_t
5529jerry_get_typedarray_length (jerry_value_t value) /**< TypedArray to query */
5530{
5531 jerry_assert_api_available ();
5532
5533#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5534 if (ecma_is_typedarray (value))
5535 {
5536 ecma_object_t *array_p = ecma_get_object_from_value (value);
5537 return ecma_typedarray_get_length (array_p);
5538 }
5539#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5540 JERRY_UNUSED (value);
5541#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5542
5543 return 0;
5544} /* jerry_get_typedarray_length */
5545
5546/**
5547 * Get the underlying ArrayBuffer from a TypedArray.
5548 *
5549 * Additionally the byteLength and byteOffset properties are also returned
5550 * which were specified when the TypedArray was created.
5551 *
5552 * Note:
5553 * the returned value must be freed with a jerry_release_value call
5554 *
5555 * @return ArrayBuffer of a TypedArray
5556 * TypeError if the object is not a TypedArray.
5557 */
5558jerry_value_t
5559jerry_get_typedarray_buffer (jerry_value_t value, /**< TypedArray to get the arraybuffer from */
5560 jerry_length_t *byte_offset, /**< [out] byteOffset property */
5561 jerry_length_t *byte_length) /**< [out] byteLength property */
5562{
5563 jerry_assert_api_available ();
5564
5565#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
5566 if (!ecma_is_typedarray (value))
5567 {
5568 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Object is not a TypedArray.")));
5569 }
5570
5571 ecma_object_t *array_p = ecma_get_object_from_value (value);
5572 uint8_t shift = ecma_typedarray_get_element_size_shift (array_p);
5573
5574 if (byte_length != NULL)
5575 {
5576 *byte_length = (jerry_length_t) (ecma_typedarray_get_length (array_p) << shift);
5577 }
5578
5579 if (byte_offset != NULL)
5580 {
5581 *byte_offset = (jerry_length_t) ecma_typedarray_get_offset (array_p);
5582 }
5583
5584 ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_p);
5585 ecma_ref_object (arraybuffer_p);
5586 return jerry_return (ecma_make_object_value (arraybuffer_p));
5587#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5588 JERRY_UNUSED (value);
5589 JERRY_UNUSED (byte_length);
5590 JERRY_UNUSED (byte_offset);
5591 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray is not supported.")));
5592#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
5593} /* jerry_get_typedarray_buffer */
5594
5595/**
5596 * Parse the given JSON string to create a jerry_value_t.
5597 *
5598 * The behaviour is equivalent with the "JSON.parse(string)" JS call.
5599 *
5600 * Note:
5601 * The returned value must be freed with jerry_release_value.
5602 *
5603 * @return - jerry_value_t containing a JavaScript value.
5604 * - Error value if there was problems during the parse.
5605 */
5606jerry_value_t
5607jerry_json_parse (const jerry_char_t *string_p, /**< json string */
5608 jerry_size_t string_size) /**< json string size */
5609{
5610 jerry_assert_api_available ();
5611
5612#if ENABLED (JERRY_BUILTIN_JSON)
5613 ecma_value_t ret_value = ecma_builtin_json_parse_buffer (string_p, string_size);
5614
5615 if (ecma_is_value_undefined (ret_value))
5616 {
5617 ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON string parse error.")));
5618 }
5619
5620 return jerry_return (ret_value);
5621#else /* !ENABLED (JERRY_BUILTIN_JSON) */
5622 JERRY_UNUSED (string_p);
5623 JERRY_UNUSED (string_size);
5624
5625 return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
5626#endif /* ENABLED (JERRY_BUILTIN_JSON) */
5627} /* jerry_json_parse */
5628
5629/**
5630 * Create a JSON string from a JavaScript value.
5631 *
5632 * The behaviour is equivalent with the "JSON.stringify(input_value)" JS call.
5633 *
5634 * Note:
5635 * The returned value must be freed with jerry_release_value,
5636 *
5637 * @return - jerry_value_t containing a JSON string.
5638 * - Error value if there was a problem during the stringification.
5639 */
5640jerry_value_t
5641jerry_json_stringify (const jerry_value_t input_value) /**< a value to stringify */
5642{
5643 jerry_assert_api_available ();
5644#if ENABLED (JERRY_BUILTIN_JSON)
5645 if (ecma_is_value_error_reference (input_value))
5646 {
5647 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
5648 }
5649
5650 ecma_value_t ret_value = ecma_builtin_json_stringify_no_opts (input_value);
5651
5652 if (ecma_is_value_undefined (ret_value))
5653 {
5654 ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON stringify error.")));
5655 }
5656
5657 return jerry_return (ret_value);
5658#else /* ENABLED (JERRY_BUILTIN_JSON) */
5659 JERRY_UNUSED (input_value);
5660
5661 return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
5662#endif /* ENABLED (JERRY_BUILTIN_JSON) */
5663} /* jerry_json_stringify */
5664
5665/**
5666 * Create a container type specified in jerry_container_type_t.
5667 * The container can be created with a list of arguments, which will be passed to the container constructor to be
5668 * inserted to the container.
5669 *
5670 * Note:
5671 * The returned value must be freed with jerry_release_value
5672 * @return jerry_value_t representing a container with the given type.
5673 */
5674jerry_value_t
5675jerry_create_container (jerry_container_type_t container_type, /**< Type of the container */
5676 const jerry_value_t *arguments_list_p, /**< arguments list */
5677 jerry_length_t arguments_list_len) /**< Length of arguments list */
5678{
5679 jerry_assert_api_available ();
5680
5681#if ENABLED (JERRY_BUILTIN_CONTAINER)
5682 for (jerry_length_t i = 0; i < arguments_list_len; i++)
5683 {
5684 if (ecma_is_value_error_reference (arguments_list_p[i]))
5685 {
5686 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
5687 }
5688 }
5689
5690 lit_magic_string_id_t lit_id;
5691 ecma_builtin_id_t proto_id;
5692 ecma_builtin_id_t ctor_id;
5693
5694 switch (container_type)
5695 {
5696#if ENABLED (JERRY_BUILTIN_MAP)
5697 case JERRY_CONTAINER_TYPE_MAP:
5698 {
5699 lit_id = LIT_MAGIC_STRING_MAP_UL;
5700 proto_id = ECMA_BUILTIN_ID_MAP_PROTOTYPE;
5701 ctor_id = ECMA_BUILTIN_ID_MAP;
5702 break;
5703 }
5704#endif /* ENABLED (JERRY_BUILTIN_MAP) */
5705#if ENABLED (JERRY_BUILTIN_SET)
5706 case JERRY_CONTAINER_TYPE_SET:
5707 {
5708 lit_id = LIT_MAGIC_STRING_SET_UL;
5709 proto_id = ECMA_BUILTIN_ID_SET_PROTOTYPE;
5710 ctor_id = ECMA_BUILTIN_ID_SET;
5711 break;
5712 }
5713#endif /* ENABLED (JERRY_BUILTIN_SET) */
5714#if ENABLED (JERRY_BUILTIN_WEAKMAP)
5715 case JERRY_CONTAINER_TYPE_WEAKMAP:
5716 {
5717 lit_id = LIT_MAGIC_STRING_WEAKMAP_UL;
5718 proto_id = ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE;
5719 ctor_id = ECMA_BUILTIN_ID_WEAKMAP;
5720 break;
5721 }
5722#endif /* ENABLED (JERRY_BUILTIN_WEAKMAP) */
5723#if ENABLED (JERRY_BUILTIN_WEAKSET)
5724 case JERRY_CONTAINER_TYPE_WEAKSET:
5725 {
5726 lit_id = LIT_MAGIC_STRING_WEAKSET_UL;
5727 proto_id = ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE;
5728 ctor_id = ECMA_BUILTIN_ID_WEAKSET;
5729 break;
5730 }
5731#endif /* ENABLED (JERRY_BUILTIN_WEAKSET) */
5732 default:
5733 {
5734 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Invalid container type.")));
5735 }
5736 }
5737 ecma_object_t * old_new_target_p = JERRY_CONTEXT (current_new_target_p);
5738
5739 if (old_new_target_p == NULL)
5740 {
5741 JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ctor_id);
5742 }
5743
5744 ecma_value_t container_value = ecma_op_container_create (arguments_list_p,
5745 arguments_list_len,
5746 lit_id,
5747 proto_id);
5748
5749 JERRY_CONTEXT (current_new_target_p) = old_new_target_p;
5750 return container_value;
5751#else /* !ENABLED (JERRY_BUILTIN_CONTAINER) */
5752 JERRY_UNUSED (arguments_list_p);
5753 JERRY_UNUSED (arguments_list_len);
5754 JERRY_UNUSED (container_type);
5755 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Containers are disabled.")));
5756#endif /* ENABLED (JERRY_BUILTIN_CONTAINER) */
5757} /* jerry_create_container */
5758
5759/**
5760 * Get the type of the given container object.
5761 *
5762 * @return Corresponding type to the given container object.
5763 */
5764jerry_container_type_t
5765jerry_get_container_type (const jerry_value_t value) /**< the container object */
5766{
5767 jerry_assert_api_available ();
5768
5769#if ENABLED (JERRY_BUILTIN_CONTAINER)
5770 if (ecma_is_value_object (value))
5771 {
5772 ecma_object_t *obj_p = ecma_get_object_from_value (value);
5773
5774 if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS)
5775 {
5776 uint16_t type = ((ecma_extended_object_t *) obj_p)->u.class_prop.class_id;
5777
5778 switch (type)
5779 {
5780#if ENABLED (JERRY_BUILTIN_MAP)
5781 case LIT_MAGIC_STRING_MAP_UL:
5782 {
5783 return JERRY_CONTAINER_TYPE_MAP;
5784 }
5785#endif /* ENABLED (JERRY_BUILTIN_MAP) */
5786#if ENABLED (JERRY_BUILTIN_SET)
5787 case LIT_MAGIC_STRING_SET_UL:
5788 {
5789 return JERRY_CONTAINER_TYPE_SET;
5790 }
5791#endif /* ENABLED (JERRY_BUILTIN_SET) */
5792#if ENABLED (JERRY_BUILTIN_WEAKMAP)
5793 case LIT_MAGIC_STRING_WEAKMAP_UL:
5794 {
5795 return JERRY_CONTAINER_TYPE_WEAKMAP;
5796 }
5797#endif /* ENABLED (JERRY_BUILTIN_WEAKMAP) */
5798#if ENABLED (JERRY_BUILTIN_WEAKSET)
5799 case LIT_MAGIC_STRING_WEAKSET_UL:
5800 {
5801 return JERRY_CONTAINER_TYPE_WEAKSET;
5802 }
5803#endif /* ENABLED (JERRY_BUILTIN_WEAKSET) */
5804 default:
5805 {
5806 return JERRY_CONTAINER_TYPE_INVALID;
5807 }
5808 }
5809 }
5810 }
5811
5812#else /* !ENABLED (JERRY_BUILTIN_CONTAINER) */
5813 JERRY_UNUSED (value);
5814#endif /* ENABLED (JERRY_BUILTIN_CONTAINER) */
5815 return JERRY_CONTAINER_TYPE_INVALID;
5816} /* jerry_get_container_type */
5817
5818/**
5819 * @}
5820 */
5821