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
18#include "debugger.h"
19#include "ecma-alloc.h"
20#include "ecma-array-object.h"
21#include "ecma-arraybuffer-object.h"
22#include "ecma-builtin-helpers.h"
23#include "ecma-builtins.h"
24#include "ecma-comparison.h"
25#include "ecma-container-object.h"
26#include "ecma-dataview-object.h"
27#include "ecma-exceptions.h"
28#include "ecma-eval.h"
29#include "ecma-function-object.h"
30#include "ecma-gc.h"
31#include "ecma-helpers.h"
32#include "ecma-init-finalize.h"
33#include "ecma-lex-env.h"
34#include "lit-char-helpers.h"
35#include "ecma-literal-storage.h"
36#include "ecma-objects.h"
37#include "ecma-objects-general.h"
38#include "ecma-regexp-object.h"
39#include "ecma-promise-object.h"
40#include "ecma-proxy-object.h"
41#include "ecma-symbol-object.h"
42#include "ecma-typedarray-object.h"
43#include "opcodes.h"
44#include "jcontext.h"
45#include "jerryscript.h"
46#include "jerryscript-debugger-transport.h"
47#include "jmem.h"
48#include "js-parser.h"
49#include "re-compiler.h"
50
51#ifdef JERRY_FOR_IAR_CONFIG
52
53#include "config-gt.h"
54
55#endif
56
57#if defined(JERRY_REF_TRACKER)
58#include "tracker.h"
59#endif
60
61#if defined(JERRY_HEAPDUMP)
62#include "heapdump.h"
63#endif
64
65JERRY_STATIC_ASSERT (sizeof (jerry_value_t) == sizeof (ecma_value_t),
66                     size_of_jerry_value_t_must_be_equal_to_size_of_ecma_value_t);
67
68JERRY_STATIC_ASSERT ((int) ECMA_ERROR_NONE == (int) JERRY_ERROR_NONE
69                     && (int) ECMA_ERROR_COMMON == (int) JERRY_ERROR_COMMON
70                     && (int) ECMA_ERROR_EVAL == (int) JERRY_ERROR_EVAL
71                     && (int) ECMA_ERROR_RANGE == (int) JERRY_ERROR_RANGE
72                     && (int) ECMA_ERROR_REFERENCE == (int) JERRY_ERROR_REFERENCE
73                     && (int) ECMA_ERROR_SYNTAX == (int) JERRY_ERROR_SYNTAX
74                     && (int) ECMA_ERROR_TYPE == (int) JERRY_ERROR_TYPE
75                     && (int) ECMA_ERROR_URI == (int) JERRY_ERROR_URI,
76                     ecma_standard_error_t_must_be_equal_to_jerry_error_t);
77
78JERRY_STATIC_ASSERT ((int) ECMA_INIT_EMPTY == (int) JERRY_INIT_EMPTY
79                     && (int) ECMA_INIT_SHOW_OPCODES == (int) JERRY_INIT_SHOW_OPCODES
80                     && (int) ECMA_INIT_SHOW_REGEXP_OPCODES == (int) JERRY_INIT_SHOW_REGEXP_OPCODES
81                     && (int) ECMA_INIT_MEM_STATS == (int) JERRY_INIT_MEM_STATS,
82                     ecma_init_flag_t_must_be_equal_to_jerry_init_flag_t);
83
84#if ENABLED (JERRY_BUILTIN_REGEXP)
85JERRY_STATIC_ASSERT ((int) RE_FLAG_GLOBAL == (int) JERRY_REGEXP_FLAG_GLOBAL
86                     && (int) RE_FLAG_MULTILINE == (int) JERRY_REGEXP_FLAG_MULTILINE
87                     && (int) RE_FLAG_IGNORE_CASE == (int) JERRY_REGEXP_FLAG_IGNORE_CASE,
88                     re_flags_t_must_be_equal_to_jerry_regexp_flags_t);
89#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
90
91#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
92/* The internal ECMA_PROMISE_STATE_* values are "one byte away" from the API values */
93JERRY_STATIC_ASSERT ((int) ECMA_PROMISE_IS_PENDING == (int) JERRY_PROMISE_STATE_PENDING
94                     && (int) ECMA_PROMISE_IS_FULFILLED == (int) JERRY_PROMISE_STATE_FULFILLED,
95                     promise_internal_state_matches_external);
96#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
97
98/**
99 * Offset between internal and external arithmetic operator types
100 */
101#define ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET (JERRY_BIN_OP_SUB - NUMBER_ARITHMETIC_SUBTRACTION)
102
103JERRY_STATIC_ASSERT (((NUMBER_ARITHMETIC_SUBTRACTION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_SUB)
104                     && ((NUMBER_ARITHMETIC_MULTIPLICATION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_MUL)
105                     && ((NUMBER_ARITHMETIC_DIVISION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_DIV)
106                     && ((NUMBER_ARITHMETIC_REMAINDER + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_REM),
107                     number_arithmetics_operation_type_matches_external);
108
109#if !ENABLED (JERRY_PARSER) && !ENABLED (JERRY_SNAPSHOT_EXEC)
110#error "JERRY_SNAPSHOT_EXEC must be enabled if JERRY_PARSER is disabled!"
111#endif /* !ENABLED (JERRY_PARSER) && !ENABLED (JERRY_SNAPSHOT_EXEC) */
112
113#if ENABLED (JERRY_ERROR_MESSAGES)
114
115/**
116 * Error message, if an argument is has an error flag
117 */
118static const char * const error_value_msg_p = "argument cannot have an error flag";
119
120/**
121 * Error message, if types of arguments are incorrect
122 */
123static const char * const wrong_args_msg_p = "wrong type of argument";
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#ifdef JERRY_FOR_IAR_CONFIG
201char* jerry_vla_malloc (uint32_t size)
202{
203  char* ret;
204  ret = OhosMalloc (MEM_TYPE_JERRY, size);
205  if (!ret)
206  {
207    return NULL;
208  }
209  return ret;
210}
211
212void jerry_vla_free (char* p)
213{
214  OhosFree (p);
215}
216#endif
217
218/**
219 * Jerry engine initialization
220 */
221void
222jerry_init (jerry_init_flag_t flags) /**< combination of Jerry flags */
223{
224#if defined(JERRY_REF_TRACKER)
225  InitTracker();
226#endif
227  /* This function cannot be called twice unless jerry_cleanup is called. */
228  JERRY_ASSERT (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_API_AVAILABLE));
229
230  /* Zero out all non-external members. */
231  memset ((char *) &JERRY_CONTEXT_STRUCT + offsetof (jerry_context_t, JERRY_CONTEXT_FIRST_MEMBER), 0,
232          sizeof (jerry_context_t) - offsetof (jerry_context_t, JERRY_CONTEXT_FIRST_MEMBER));
233
234  JERRY_CONTEXT (jerry_init_flags) = flags;
235
236  jerry_make_api_available ();
237
238  jmem_init ();
239  ecma_init ();
240} /* jerry_init */
241
242/**
243 * Terminate Jerry engine
244 */
245void
246jerry_cleanup (void)
247{
248  ecma_gc_run();
249
250  jerry_assert_api_available ();
251
252#if ENABLED (JERRY_DEBUGGER)
253  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
254  {
255    jerry_debugger_send_type (JERRY_DEBUGGER_CLOSE_CONNECTION);
256
257    jerry_debugger_transport_close ();
258  }
259#endif /* ENABLED (JERRY_DEBUGGER) */
260
261  for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p);
262       this_p != NULL;
263       this_p = this_p->next_p)
264  {
265    if (this_p->manager_p->deinit_cb)
266    {
267      void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL;
268      this_p->manager_p->deinit_cb (data);
269    }
270  }
271
272#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
273  ecma_free_all_enqueued_jobs ();
274#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
275  ecma_finalize ();
276  jerry_make_api_unavailable ();
277
278  for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p), *next_p = NULL;
279       this_p != NULL;
280       this_p = next_p)
281  {
282    next_p = this_p->next_p;
283    if (this_p->manager_p->finalize_cb)
284    {
285      void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL;
286      this_p->manager_p->finalize_cb (data);
287    }
288    jmem_heap_free_block (this_p, sizeof (jerry_context_data_header_t) + this_p->manager_p->bytes_needed);
289  }
290
291  jmem_finalize ();
292} /* jerry_cleanup */
293
294/**
295 * Retrieve a context data item, or create a new one.
296 *
297 * @param manager_p pointer to the manager whose context data item should be returned.
298 *
299 * @return a pointer to the user-provided context-specific data item for the given manager, creating such a pointer if
300 * none was found.
301 */
302void *
303jerry_get_context_data (const jerry_context_data_manager_t *manager_p)
304{
305  void *ret = NULL;
306  jerry_context_data_header_t *item_p;
307
308  for (item_p = JERRY_CONTEXT (context_data_p); item_p != NULL; item_p = item_p->next_p)
309  {
310    if (item_p->manager_p == manager_p)
311    {
312      return (manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p) : NULL;
313    }
314  }
315
316  item_p = jmem_heap_alloc_block (sizeof (jerry_context_data_header_t) + manager_p->bytes_needed);
317  item_p->manager_p = manager_p;
318  item_p->next_p = JERRY_CONTEXT (context_data_p);
319  JERRY_CONTEXT (context_data_p) = item_p;
320
321  if (manager_p->bytes_needed > 0)
322  {
323    ret = JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p);
324    memset (ret, 0, manager_p->bytes_needed);
325  }
326
327  if (manager_p->init_cb)
328  {
329    manager_p->init_cb (ret);
330  }
331
332  return ret;
333} /* jerry_get_context_data */
334
335/**
336 * Register external magic string array
337 */
338void
339jerry_register_magic_strings (const jerry_char_t * const *ex_str_items_p, /**< character arrays, representing
340                                                                           *   external magic strings' contents */
341                              uint32_t count, /**< number of the strings */
342                              const jerry_length_t *str_lengths_p) /**< lengths of all strings */
343{
344  jerry_assert_api_available ();
345
346  lit_magic_strings_ex_set ((const lit_utf8_byte_t * const *) ex_str_items_p,
347                            count,
348                            (const lit_utf8_size_t *) str_lengths_p);
349} /* jerry_register_magic_strings */
350
351/**
352 * Run garbage collection
353 */
354void
355jerry_gc (jerry_gc_mode_t mode) /**< operational mode */
356{
357  jerry_assert_api_available ();
358
359  if (mode == JERRY_GC_PRESSURE_LOW)
360  {
361    /* Call GC directly, because 'ecma_free_unused_memory' might decide it's not yet worth it. */
362    ecma_gc_run ();
363    return;
364  }
365
366  ecma_free_unused_memory (JMEM_PRESSURE_HIGH);
367} /* jerry_gc */
368
369/**
370 * Get heap memory stats.
371 *
372 * @return true - get the heap stats successful
373 *         false - otherwise. Usually it is because the MEM_STATS feature is not enabled.
374 */
375bool
376jerry_get_memory_stats (jerry_heap_stats_t *out_stats_p) /**< [out] heap memory stats */
377{
378#if ENABLED (JERRY_MEM_STATS)
379  if (out_stats_p == NULL)
380  {
381    return false;
382  }
383
384  jmem_heap_stats_t jmem_heap_stats;
385  memset (&jmem_heap_stats, 0, sizeof (jmem_heap_stats));
386  jmem_heap_get_stats (&jmem_heap_stats);
387
388  *out_stats_p = (jerry_heap_stats_t)
389  {
390    .version = 1,
391    .size = jmem_heap_stats.size,
392    .allocated_bytes = jmem_heap_stats.allocated_bytes,
393    .peak_allocated_bytes = jmem_heap_stats.peak_allocated_bytes
394  };
395
396  return true;
397#else /* !ENABLED (JERRY_MEM_STATS) */
398  JERRY_UNUSED (out_stats_p);
399  return false;
400#endif /* ENABLED (JERRY_MEM_STATS) */
401} /* jerry_get_memory_stats */
402
403/**
404 * Simple Jerry runner
405 *
406 * @return true  - if run was successful
407 *         false - otherwise
408 */
409bool
410jerry_run_simple (const jerry_char_t *script_source_p, /**< script source */
411                  size_t script_source_size, /**< script source size */
412                  jerry_init_flag_t flags) /**< combination of Jerry flags */
413{
414  bool result = false;
415
416  jerry_init (flags);
417
418  jerry_value_t parse_ret_val = jerry_parse (NULL, 0, script_source_p, script_source_size, JERRY_PARSE_NO_OPTS);
419
420  if (!ecma_is_value_error_reference (parse_ret_val))
421  {
422    jerry_value_t run_ret_val = jerry_run (parse_ret_val);
423
424    if (!ecma_is_value_error_reference (run_ret_val))
425    {
426      result = true;
427    }
428
429    jerry_release_value (run_ret_val);
430  }
431
432  jerry_release_value (parse_ret_val);
433  jerry_cleanup ();
434
435  return result;
436} /* jerry_run_simple */
437
438/**
439 * Parse script and construct an EcmaScript function. The lexical
440 * environment is set to the global lexical environment.
441 *
442 * @return function object value - if script was parsed successfully,
443 *         thrown error - otherwise
444 */
445jerry_value_t
446jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a file name) */
447             size_t resource_name_length, /**< length of resource name */
448             const jerry_char_t *source_p, /**< script source */
449             size_t source_size, /**< script source size */
450             uint32_t parse_opts) /**< jerry_parse_opts_t option bits */
451{
452#if ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)
453  if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
454      && resource_name_length > 0)
455  {
456    jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
457                                JERRY_DEBUGGER_NO_SUBTYPE,
458                                resource_name_p,
459                                resource_name_length);
460  }
461#else /* !(ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)) */
462  JERRY_UNUSED (resource_name_p);
463  JERRY_UNUSED (resource_name_length);
464#endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
465
466#if ENABLED (JERRY_PARSER)
467  jerry_assert_api_available ();
468
469#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
470  if (resource_name_length == 0)
471  {
472    JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
473  }
474  else
475  {
476    JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p,
477                                                                        (lit_utf8_size_t) resource_name_length);
478  }
479#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
480
481  ecma_compiled_code_t *bytecode_data_p;
482  ecma_value_t parse_status;
483
484  parse_status = parser_parse_script (NULL,
485                                      0,
486                                      source_p,
487                                      source_size,
488                                      parse_opts,
489                                      &bytecode_data_p);
490
491  if (ECMA_IS_VALUE_ERROR (parse_status))
492  {
493    return ecma_create_error_reference_from_context ();
494  }
495
496  ecma_free_value (parse_status);
497
498  ecma_object_t *lex_env_p = ecma_get_global_environment ();
499  ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
500  ecma_bytecode_deref (bytecode_data_p);
501
502  return ecma_make_object_value (func_obj_p);
503#else /* !ENABLED (JERRY_PARSER) */
504  JERRY_UNUSED (source_p);
505  JERRY_UNUSED (source_size);
506  JERRY_UNUSED (parse_opts);
507
508  return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled.")));
509#endif /* ENABLED (JERRY_PARSER) */
510} /* jerry_parse */
511
512/**
513 * Parse function and construct an EcmaScript function. The lexical
514 * environment is set to the global lexical environment.
515 *
516 * @return function object value - if script was parsed successfully,
517 *         thrown error - otherwise
518 */
519jerry_value_t
520jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (usually a file name) */
521                      size_t resource_name_length, /**< length of resource name */
522                      const jerry_char_t *arg_list_p, /**< script source */
523                      size_t arg_list_size, /**< script source size */
524                      const jerry_char_t *source_p, /**< script source */
525                      size_t source_size, /**< script source size */
526                      uint32_t parse_opts) /**< jerry_parse_opts_t option bits */
527{
528#if ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)
529  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
530  {
531    jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
532                                JERRY_DEBUGGER_NO_SUBTYPE,
533                                resource_name_p,
534                                resource_name_length);
535  }
536#else /* !(ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)) */
537  JERRY_UNUSED (resource_name_p);
538  JERRY_UNUSED (resource_name_length);
539#endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
540
541#if ENABLED (JERRY_PARSER)
542  jerry_assert_api_available ();
543
544  ecma_compiled_code_t *bytecode_data_p;
545  ecma_value_t parse_status;
546
547#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
548  if (resource_name_length == 0)
549  {
550    JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
551  }
552  else
553  {
554    JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p,
555                                                                        (lit_utf8_size_t) resource_name_length);
556  }
557#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
558
559  if (arg_list_p == NULL)
560  {
561    /* Must not be a NULL value. */
562    arg_list_p = (const jerry_char_t *) "";
563  }
564
565  parse_status = parser_parse_script (arg_list_p,
566                                      arg_list_size,
567                                      source_p,
568                                      source_size,
569                                      parse_opts,
570                                      &bytecode_data_p);
571
572  if (ECMA_IS_VALUE_ERROR (parse_status))
573  {
574    return ecma_create_error_reference_from_context ();
575  }
576
577  ecma_free_value (parse_status);
578
579  ecma_object_t *lex_env_p = ecma_get_global_environment ();
580  ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
581  ecma_bytecode_deref (bytecode_data_p);
582
583  return ecma_make_object_value (func_obj_p);
584#else /* !ENABLED (JERRY_PARSER) */
585  JERRY_UNUSED (arg_list_p);
586  JERRY_UNUSED (arg_list_size);
587  JERRY_UNUSED (source_p);
588  JERRY_UNUSED (source_size);
589  JERRY_UNUSED (parse_opts);
590
591  return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled.")));
592#endif /* ENABLED (JERRY_PARSER) */
593} /* jerry_parse_function */
594
595/**
596 * Run an EcmaScript function created by jerry_parse.
597 *
598 * Note:
599 *      returned value must be freed with jerry_release_value, when it is no longer needed.
600 *
601 * @return result of bytecode - if run was successful
602 *         thrown error - otherwise
603 */
604jerry_value_t
605jerry_run (const jerry_value_t func_val) /**< function to run */
606{
607  jerry_assert_api_available ();
608
609  if (!ecma_is_value_object (func_val))
610  {
611    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
612  }
613
614  ecma_object_t *func_obj_p = ecma_get_object_from_value (func_val);
615
616  if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION
617      || ecma_get_object_is_builtin (func_obj_p))
618  {
619    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
620  }
621
622  ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p;
623
624  ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
625                                                                       ext_func_p->u.function.scope_cp);
626
627  if (scope_p != ecma_get_global_environment ())
628  {
629    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
630  }
631
632  return jerry_return (vm_run_global (ecma_op_function_get_compiled_code (ext_func_p)));
633} /* jerry_run */
634
635/**
636 * Perform eval
637 *
638 * Note:
639 *      returned value must be freed with jerry_release_value, when it is no longer needed.
640 *
641 * @return result of eval, may be error value.
642 */
643jerry_value_t
644jerry_eval (const jerry_char_t *source_p, /**< source code */
645            size_t source_size, /**< length of source code */
646            uint32_t parse_opts) /**< jerry_parse_opts_t option bits */
647{
648  jerry_assert_api_available ();
649
650  return jerry_return (ecma_op_eval_chars_buffer ((const lit_utf8_byte_t *) source_p,
651                                                  source_size,
652                                                  parse_opts));
653} /* jerry_eval */
654
655/**
656 * Run enqueued Promise jobs until the first thrown error or until all get executed.
657 *
658 * Note:
659 *      returned value must be freed with jerry_release_value, when it is no longer needed.
660 *
661 * @return result of last executed job, may be error value.
662 */
663jerry_value_t
664jerry_run_all_enqueued_jobs (void)
665{
666  jerry_assert_api_available ();
667
668#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
669  return ecma_process_all_enqueued_jobs ();
670#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
671  return ECMA_VALUE_UNDEFINED;
672#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
673} /* jerry_run_all_enqueued_jobs */
674
675/**
676 * Get global object
677 *
678 * Note:
679 *      returned value must be freed with jerry_release_value, when it is no longer needed.
680 *
681 * @return api value of global object
682 */
683jerry_value_t
684jerry_get_global_object (void)
685{
686  jerry_assert_api_available ();
687  ecma_object_t *global_obj_p = ecma_builtin_get_global ();
688  ecma_ref_object (global_obj_p);
689  return ecma_make_object_value (global_obj_p);
690} /* jerry_get_global_object */
691
692/**
693 * Check if the specified value is an abort value.
694 *
695 * @return true  - if both the error and abort values are set,
696 *         false - otherwise
697 */
698bool
699jerry_value_is_abort (const jerry_value_t value) /**< api value */
700{
701  jerry_assert_api_available ();
702
703  if (!ecma_is_value_error_reference (value))
704  {
705    return false;
706  }
707
708  ecma_error_reference_t *error_ref_p = ecma_get_error_reference_from_value (value);
709
710  return (error_ref_p->refs_and_flags & ECMA_ERROR_REF_ABORT) != 0;
711} /* jerry_value_is_abort */
712
713/**
714 * Check if the specified value is an array object value.
715 *
716 * @return true  - if the specified value is an array object,
717 *         false - otherwise
718 */
719bool
720jerry_value_is_array (const jerry_value_t value) /**< jerry api value */
721{
722  jerry_assert_api_available ();
723
724  return (ecma_is_value_object (value)
725          && ecma_get_object_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_TYPE_ARRAY);
726} /* jerry_value_is_array */
727
728/**
729 * Check if the specified value is boolean.
730 *
731 * @return true  - if the specified value is boolean,
732 *         false - otherwise
733 */
734bool
735jerry_value_is_boolean (const jerry_value_t value) /**< api value */
736{
737  jerry_assert_api_available ();
738
739  return ecma_is_value_boolean (value);
740} /* jerry_value_is_boolean */
741
742/**
743 * Check if the specified value is a constructor function object value.
744 *
745 * @return true - if the specified value is a function value that implements [[Construct]],
746 *         false - otherwise
747 */
748bool
749jerry_value_is_constructor (const jerry_value_t value) /**< jerry api value */
750{
751  jerry_assert_api_available ();
752
753  return ecma_is_constructor (value);
754} /* jerry_value_is_constructor */
755
756/**
757 * Check if the specified value is an error or abort value.
758 *
759 * @return true  - if the specified value is an error value,
760 *         false - otherwise
761 */
762bool
763jerry_value_is_error (const jerry_value_t value) /**< api value */
764{
765  jerry_assert_api_available ();
766
767  return ecma_is_value_error_reference (value);
768} /* jerry_value_is_error */
769
770/**
771 * Check if the specified value is a function object value.
772 *
773 * @return true - if the specified value is callable,
774 *         false - otherwise
775 */
776bool
777jerry_value_is_function (const jerry_value_t value) /**< api value */
778{
779  jerry_assert_api_available ();
780
781  return ecma_op_is_callable (value);
782} /* jerry_value_is_function */
783
784/**
785 * Check if the specified value is number.
786 *
787 * @return true  - if the specified value is number,
788 *         false - otherwise
789 */
790bool
791jerry_value_is_number (const jerry_value_t value) /**< api value */
792{
793  jerry_assert_api_available ();
794
795  return ecma_is_value_number (value);
796} /* jerry_value_is_number */
797
798/**
799 * Check if the specified value is null.
800 *
801 * @return true  - if the specified value is null,
802 *         false - otherwise
803 */
804bool
805jerry_value_is_null (const jerry_value_t value) /**< api value */
806{
807  jerry_assert_api_available ();
808
809  return ecma_is_value_null (value);
810} /* jerry_value_is_null */
811
812/**
813 * Check if the specified value is object.
814 *
815 * @return true  - if the specified value is object,
816 *         false - otherwise
817 */
818bool
819jerry_value_is_object (const jerry_value_t value) /**< api value */
820{
821  jerry_assert_api_available ();
822
823  return ecma_is_value_object (value);
824} /* jerry_value_is_object */
825
826/**
827 * Check if the specified value is promise.
828 *
829 * @return true  - if the specified value is promise,
830 *         false - otherwise
831 */
832bool
833jerry_value_is_promise (const jerry_value_t value) /**< api value */
834{
835  jerry_assert_api_available ();
836#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
837  return (ecma_is_value_object (value)
838          && ecma_is_promise (ecma_get_object_from_value (value)));
839#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
840  JERRY_UNUSED (value);
841  return false;
842#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
843} /* jerry_value_is_promise */
844
845/**
846 * Check if the specified value is a proxy object.
847 *
848 * @return true  - if the specified value is a proxy object,
849 *         false - otherwise
850 */
851bool
852jerry_value_is_proxy (const jerry_value_t value) /**< api value */
853{
854  jerry_assert_api_available ();
855#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
856  return (ecma_is_value_object (value)
857          && ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (value)));
858#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
859  JERRY_UNUSED (value);
860  return false;
861#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
862} /* jerry_value_is_proxy */
863
864/**
865 * Check if the specified value is string.
866 *
867 * @return true  - if the specified value is string,
868 *         false - otherwise
869 */
870bool
871jerry_value_is_string (const jerry_value_t value) /**< api value */
872{
873  jerry_assert_api_available ();
874
875  return ecma_is_value_string (value);
876} /* jerry_value_is_string */
877
878/**
879 * Check if the specified value is symbol.
880 *
881 * @return true  - if the specified value is symbol,
882 *         false - otherwise
883 */
884bool
885jerry_value_is_symbol (const jerry_value_t value) /**< api value */
886{
887  jerry_assert_api_available ();
888
889#if ENABLED (JERRY_ES2015)
890  return ecma_is_value_symbol (value);
891#else /* !ENABLED (JERRY_ES2015) */
892  JERRY_UNUSED (value);
893  return false;
894#endif /* ENABLED (JERRY_ES2015) */
895} /* jerry_value_is_symbol */
896
897/**
898 * Check if the specified value is undefined.
899 *
900 * @return true  - if the specified value is undefined,
901 *         false - otherwise
902 */
903bool
904jerry_value_is_undefined (const jerry_value_t value) /**< api value */
905{
906  jerry_assert_api_available ();
907
908  return ecma_is_value_undefined (value);
909} /* jerry_value_is_undefined */
910
911/**
912 * Perform the base type of the JavaScript value.
913 *
914 * @return jerry_type_t value
915 */
916jerry_type_t
917jerry_value_get_type (const jerry_value_t value) /**< input value to check */
918{
919  jerry_assert_api_available ();
920
921  if (ecma_is_value_error_reference (value))
922  {
923    return JERRY_TYPE_ERROR;
924  }
925
926  lit_magic_string_id_t lit_id = ecma_get_typeof_lit_id (value);
927
928  JERRY_ASSERT (lit_id != LIT_MAGIC_STRING__EMPTY);
929
930  switch (lit_id)
931  {
932    case LIT_MAGIC_STRING_UNDEFINED:
933    {
934      return JERRY_TYPE_UNDEFINED;
935    }
936    case LIT_MAGIC_STRING_BOOLEAN:
937    {
938      return JERRY_TYPE_BOOLEAN;
939    }
940    case LIT_MAGIC_STRING_NUMBER:
941    {
942      return JERRY_TYPE_NUMBER;
943    }
944    case LIT_MAGIC_STRING_STRING:
945    {
946      return JERRY_TYPE_STRING;
947    }
948#if ENABLED (JERRY_ES2015)
949    case LIT_MAGIC_STRING_SYMBOL:
950    {
951      return JERRY_TYPE_SYMBOL;
952    }
953#endif /* ENABLED (JERRY_ES2015) */
954    case LIT_MAGIC_STRING_FUNCTION:
955    {
956      return JERRY_TYPE_FUNCTION;
957    }
958    default:
959    {
960      JERRY_ASSERT (lit_id == LIT_MAGIC_STRING_OBJECT);
961
962      /* Based on the ECMA 262 5.1 standard the 'null' value is an object.
963       * Thus we'll do an extra check for 'null' here.
964       */
965      return ecma_is_value_null (value) ? JERRY_TYPE_NULL : JERRY_TYPE_OBJECT;
966    }
967  }
968} /* jerry_value_get_type */
969
970/**
971 * Check if the specified feature is enabled.
972 *
973 * @return true  - if the specified feature is enabled,
974 *         false - otherwise
975 */
976bool
977jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check */
978{
979  JERRY_ASSERT (feature < JERRY_FEATURE__COUNT);
980
981  return (false
982#if ENABLED (JERRY_CPOINTER_32_BIT)
983          || feature == JERRY_FEATURE_CPOINTER_32_BIT
984#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
985#if ENABLED (JERRY_ERROR_MESSAGES)
986          || feature == JERRY_FEATURE_ERROR_MESSAGES
987#endif /* ENABLED (JERRY_ERROR_MESSAGES) */
988#if ENABLED (JERRY_PARSER)
989          || feature == JERRY_FEATURE_JS_PARSER
990#endif /* ENABLED (JERRY_PARSER) */
991#if ENABLED (JERRY_MEM_STATS)
992          || feature == JERRY_FEATURE_MEM_STATS
993#endif /* ENABLED (JERRY_MEM_STATS) */
994#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
995          || feature == JERRY_FEATURE_PARSER_DUMP
996#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
997#if ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE)
998          || feature == JERRY_FEATURE_REGEXP_DUMP
999#endif /* ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE) */
1000#if ENABLED (JERRY_SNAPSHOT_SAVE)
1001          || feature == JERRY_FEATURE_SNAPSHOT_SAVE
1002#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
1003#if ENABLED (JERRY_SNAPSHOT_EXEC)
1004          || feature == JERRY_FEATURE_SNAPSHOT_EXEC
1005#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
1006#if ENABLED (JERRY_DEBUGGER)
1007          || feature == JERRY_FEATURE_DEBUGGER
1008#endif /* ENABLED (JERRY_DEBUGGER) */
1009#if ENABLED (JERRY_VM_EXEC_STOP)
1010          || feature == JERRY_FEATURE_VM_EXEC_STOP
1011#endif /* ENABLED (JERRY_VM_EXEC_STOP) */
1012#if ENABLED (JERRY_BUILTIN_JSON)
1013          || feature == JERRY_FEATURE_JSON
1014#endif /* ENABLED (JERRY_BUILTIN_JSON) */
1015#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
1016          || feature == JERRY_FEATURE_PROMISE
1017#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
1018#if ENABLED (JERRY_ES2015)
1019          || feature == JERRY_FEATURE_SYMBOL
1020#endif /* ENABLED (JERRY_ES2015) */
1021#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
1022          || feature == JERRY_FEATURE_TYPEDARRAY
1023#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
1024#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
1025          || feature == JERRY_FEATURE_DATAVIEW
1026#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
1027#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
1028          || feature == JERRY_FEATURE_PROXY
1029#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
1030#if ENABLED (JERRY_BUILTIN_DATE)
1031          || feature == JERRY_FEATURE_DATE
1032#endif /* ENABLED (JERRY_BUILTIN_DATE) */
1033#if ENABLED (JERRY_BUILTIN_REGEXP)
1034          || feature == JERRY_FEATURE_REGEXP
1035#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
1036#if ENABLED (JERRY_LINE_INFO)
1037          || feature == JERRY_FEATURE_LINE_INFO
1038#endif /* ENABLED (JERRY_LINE_INFO) */
1039#if ENABLED (JERRY_LOGGING)
1040          || feature == JERRY_FEATURE_LOGGING
1041#endif /* ENABLED (JERRY_LOGGING) */
1042#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
1043          || feature == JERRY_FEATURE_MAP
1044#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
1045#if ENABLED (JERRY_ES2015_BUILTIN_SET)
1046          || feature == JERRY_FEATURE_SET
1047#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
1048#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP)
1049          || feature == JERRY_FEATURE_WEAKMAP
1050#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
1051#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
1052          || feature == JERRY_FEATURE_WEAKSET
1053#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
1054          );
1055} /* jerry_is_feature_enabled */
1056
1057/**
1058 * Perform binary operation on the given operands (==, ===, <, >, etc.).
1059 *
1060 * @return error - if argument has an error flag or operation is unsuccessful or unsupported
1061 *         true/false - the result of the binary operation on the given operands otherwise
1062 */
1063jerry_value_t
1064jerry_binary_operation (jerry_binary_operation_t op, /**< operation */
1065                        const jerry_value_t lhs, /**< first operand */
1066                        const jerry_value_t rhs) /**< second operand */
1067{
1068  jerry_assert_api_available ();
1069
1070  if (ecma_is_value_error_reference (lhs) || ecma_is_value_error_reference (rhs))
1071  {
1072    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1073  }
1074
1075  switch (op)
1076  {
1077    case JERRY_BIN_OP_EQUAL:
1078    {
1079      return jerry_return (ecma_op_abstract_equality_compare (lhs, rhs));
1080    }
1081    case JERRY_BIN_OP_STRICT_EQUAL:
1082    {
1083      return ecma_make_boolean_value (ecma_op_strict_equality_compare (lhs, rhs));
1084    }
1085    case JERRY_BIN_OP_LESS:
1086    {
1087      return jerry_return (opfunc_relation (lhs, rhs, true, false));
1088    }
1089    case JERRY_BIN_OP_LESS_EQUAL:
1090    {
1091      return jerry_return (opfunc_relation (lhs, rhs, false, true));
1092    }
1093    case JERRY_BIN_OP_GREATER:
1094    {
1095      return jerry_return (opfunc_relation (lhs, rhs, false, false));
1096    }
1097    case JERRY_BIN_OP_GREATER_EQUAL:
1098    {
1099      return jerry_return (opfunc_relation (lhs, rhs, true, true));
1100    }
1101    case JERRY_BIN_OP_INSTANCEOF:
1102    {
1103      if (!ecma_is_value_object (lhs)
1104          || !ecma_op_is_callable (rhs))
1105      {
1106        return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
1107      }
1108
1109      ecma_object_t *proto_obj_p = ecma_get_object_from_value (rhs);
1110      return jerry_return (ecma_op_object_has_instance (proto_obj_p, lhs));
1111    }
1112    case JERRY_BIN_OP_ADD:
1113    {
1114      return jerry_return (opfunc_addition (lhs, rhs));
1115    }
1116    case JERRY_BIN_OP_SUB:
1117    case JERRY_BIN_OP_MUL:
1118    case JERRY_BIN_OP_DIV:
1119    case JERRY_BIN_OP_REM:
1120    {
1121      return jerry_return (do_number_arithmetic (op - ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET, lhs, rhs));
1122    }
1123    default:
1124    {
1125      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Unsupported binary operation")));
1126    }
1127  }
1128} /* jerry_binary_operation */
1129
1130/**
1131 * Create abort from an api value.
1132 *
1133 * Create abort value from an api value. If the second argument is true
1134 * it will release the input api value.
1135 *
1136 * @return api abort value
1137 */
1138jerry_value_t
1139jerry_create_abort_from_value (jerry_value_t value, /**< api value */
1140                               bool release) /**< release api value */
1141{
1142  jerry_assert_api_available ();
1143
1144  if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1145  {
1146    /* This is a rare case so it is optimized for
1147     * binary size rather than performance. */
1148    if (jerry_value_is_abort (value))
1149    {
1150      return release ? value : jerry_acquire_value (value);
1151    }
1152
1153    value = jerry_get_value_from_error (value, release);
1154    release = true;
1155  }
1156
1157  if (!release)
1158  {
1159    value = ecma_copy_value (value);
1160  }
1161
1162  return ecma_create_error_reference (value, false);
1163} /* jerry_create_abort_from_value */
1164
1165/**
1166 * Create error from an api value.
1167 *
1168 * Create error value from an api value. If the second argument is true
1169 * it will release the input api value.
1170 *
1171 * @return api error value
1172 */
1173jerry_value_t
1174jerry_create_error_from_value (jerry_value_t value, /**< api value */
1175                               bool release) /**< release api value */
1176{
1177  jerry_assert_api_available ();
1178
1179  if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1180  {
1181    /* This is a rare case so it is optimized for
1182     * binary size rather than performance. */
1183    if (!jerry_value_is_abort (value))
1184    {
1185      return release ? value : jerry_acquire_value (value);
1186    }
1187
1188    value = jerry_get_value_from_error (value, release);
1189    release = true;
1190  }
1191
1192  if (!release)
1193  {
1194    value = ecma_copy_value (value);
1195  }
1196
1197  return ecma_create_error_reference (value, true);
1198} /* jerry_create_error_from_value */
1199
1200/**
1201 * Get the value from an error value.
1202 *
1203 * Extract the api value from an error. If the second argument is true
1204 * it will release the input error value.
1205 *
1206 * Note:
1207 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1208 *
1209 * @return jerry_value_t value
1210 */
1211jerry_value_t
1212jerry_get_value_from_error (jerry_value_t value, /**< api value */
1213                            bool release) /**< release api value */
1214{
1215  jerry_assert_api_available ();
1216
1217  if (!ecma_is_value_error_reference (value))
1218  {
1219    return release ? value : ecma_copy_value (value);
1220  }
1221
1222  jerry_value_t ret_val = jerry_acquire_value (ecma_get_error_reference_from_value (value)->value);
1223
1224  if (release)
1225  {
1226    jerry_release_value (value);
1227  }
1228  return ret_val;
1229} /* jerry_get_value_from_error */
1230
1231/**
1232 * Return the type of the Error object if possible.
1233 *
1234 * @return one of the jerry_error_t value as the type of the Error object
1235 *         JERRY_ERROR_NONE - if the input value is not an Error object
1236 */
1237jerry_error_t
1238jerry_get_error_type (jerry_value_t value) /**< api value */
1239{
1240  if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1241  {
1242    value = ecma_get_error_reference_from_value (value)->value;
1243  }
1244
1245  if (!ecma_is_value_object (value))
1246  {
1247    return JERRY_ERROR_NONE;
1248  }
1249
1250  ecma_object_t *object_p = ecma_get_object_from_value (value);
1251  ecma_standard_error_t error_type = ecma_get_error_type (object_p);
1252
1253  return (jerry_error_t) error_type;
1254} /* jerry_get_error_type */
1255
1256/**
1257 * Get boolean from the specified value.
1258 *
1259 * @return true or false.
1260 */
1261bool
1262jerry_get_boolean_value (const jerry_value_t value) /**< api value */
1263{
1264  jerry_assert_api_available ();
1265
1266  return ecma_is_value_true (value);
1267} /* jerry_get_boolean_value */
1268
1269/**
1270 * Get number from the specified value as a double.
1271 *
1272 * @return stored number as double
1273 */
1274double
1275jerry_get_number_value (const jerry_value_t value) /**< api value */
1276{
1277  jerry_assert_api_available ();
1278
1279  if (!ecma_is_value_number (value))
1280  {
1281    return 0;
1282  }
1283
1284  return (double) ecma_get_number_from_value (value);
1285} /* jerry_get_number_value */
1286
1287/**
1288 * Call ToBoolean operation on the api value.
1289 *
1290 * @return true  - if the logical value is true
1291 *         false - otherwise
1292 */
1293bool
1294jerry_value_to_boolean (const jerry_value_t value) /**< input value */
1295{
1296  jerry_assert_api_available ();
1297
1298  if (ecma_is_value_error_reference (value))
1299  {
1300    return false;
1301  }
1302
1303  return ecma_op_to_boolean (value);
1304} /* jerry_value_to_boolean */
1305
1306/**
1307 * Call ToNumber operation on the api value.
1308 *
1309 * Note:
1310 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1311 *
1312 * @return converted number value - if success
1313 *         thrown error - otherwise
1314 */
1315jerry_value_t
1316jerry_value_to_number (const jerry_value_t value) /**< input value */
1317{
1318  jerry_assert_api_available ();
1319
1320  if (ecma_is_value_error_reference (value))
1321  {
1322    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1323  }
1324
1325  return jerry_return (ecma_op_to_number (value));
1326} /* jerry_value_to_number */
1327
1328/**
1329 * Call ToObject operation on the api value.
1330 *
1331 * Note:
1332 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1333 *
1334 * @return converted object value - if success
1335 *         thrown error - otherwise
1336 */
1337jerry_value_t
1338jerry_value_to_object (const jerry_value_t value) /**< input value */
1339{
1340  jerry_assert_api_available ();
1341
1342  if (ecma_is_value_error_reference (value))
1343  {
1344    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1345  }
1346
1347  return jerry_return (ecma_op_to_object (value));
1348} /* jerry_value_to_object */
1349
1350/**
1351 * Call ToPrimitive operation on the api value.
1352 *
1353 * Note:
1354 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1355 *
1356 * @return converted primitive value - if success
1357 *         thrown error - otherwise
1358 */
1359jerry_value_t
1360jerry_value_to_primitive (const jerry_value_t value) /**< input value */
1361{
1362  jerry_assert_api_available ();
1363
1364  if (ecma_is_value_error_reference (value))
1365  {
1366    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1367  }
1368
1369  return jerry_return (ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NO));
1370} /* jerry_value_to_primitive */
1371
1372/**
1373 * Call the ToString ecma builtin operation on the api value.
1374 *
1375 * Note:
1376 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1377 *
1378 * @return converted string value - if success
1379 *         thrown error - otherwise
1380 */
1381jerry_value_t
1382jerry_value_to_string (const jerry_value_t value) /**< input value */
1383{
1384
1385  jerry_assert_api_available ();
1386
1387  if (ecma_is_value_error_reference (value))
1388  {
1389    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
1390  }
1391
1392  ecma_string_t *str_p = ecma_op_to_string (value);
1393  if (JERRY_UNLIKELY (str_p == NULL))
1394  {
1395    return ecma_create_error_reference_from_context ();
1396  }
1397
1398  return jerry_return (ecma_make_string_value (str_p));
1399} /* jerry_value_to_string */
1400
1401/**
1402 * Acquire specified Jerry API value.
1403 *
1404 * Note:
1405 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1406 *
1407 * @return acquired api value
1408 */
1409jerry_value_t
1410jerry_acquire_value (jerry_value_t value) /**< API value */
1411{
1412  jerry_assert_api_available ();
1413
1414  if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1415  {
1416    ecma_ref_error_reference (ecma_get_error_reference_from_value (value));
1417    return value;
1418  }
1419
1420  return ecma_copy_value (value);
1421} /* jerry_acquire_value */
1422
1423/**
1424 * Release specified Jerry API value
1425 */
1426void
1427jerry_release_value (jerry_value_t value) /**< API value */
1428{
1429  jerry_assert_api_available ();
1430
1431  if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
1432  {
1433    ecma_deref_error_reference (ecma_get_error_reference_from_value (value));
1434    return;
1435  }
1436
1437  ecma_free_value (value);
1438} /* jerry_release_value */
1439
1440/**
1441 * Create an array object value
1442 *
1443 * Note:
1444 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1445 *
1446 * @return value of the constructed array object
1447 */
1448jerry_value_t
1449jerry_create_array (uint32_t size) /**< size of array */
1450{
1451  jerry_assert_api_available ();
1452
1453  ecma_value_t array_length = ecma_make_uint32_value (size);
1454
1455  const jerry_length_t argument_size = 1;
1456  ecma_value_t array_value = ecma_op_create_array_object (&array_length, argument_size, true);
1457  ecma_free_value (array_length);
1458
1459  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value));
1460
1461  return array_value;
1462} /* jerry_create_array */
1463
1464/**
1465 * Create a jerry_value_t representing a boolean value from the given boolean parameter.
1466 *
1467 * @return value of the created boolean
1468 */
1469jerry_value_t
1470jerry_create_boolean (bool value) /**< bool value from which a jerry_value_t will be created */
1471{
1472  jerry_assert_api_available ();
1473
1474  return jerry_return (ecma_make_boolean_value (value));
1475} /* jerry_create_boolean */
1476
1477/**
1478 * Create an error object
1479 *
1480 * Note:
1481 *      - returned value must be freed with jerry_release_value, when it is no longer needed
1482 *      - the error flag is set for the returned value
1483 *
1484 * @return value of the constructed error object
1485 */
1486jerry_value_t
1487jerry_create_error (jerry_error_t error_type, /**< type of error */
1488                    const jerry_char_t *message_p) /**< value of 'message' property
1489                                                    *   of constructed error object */
1490{
1491  return jerry_create_error_sz (error_type,
1492                                (lit_utf8_byte_t *) message_p,
1493                                lit_zt_utf8_string_size (message_p));
1494} /* jerry_create_error */
1495
1496/**
1497 * Create an error object
1498 *
1499 * Note:
1500 *      - returned value must be freed with jerry_release_value, when it is no longer needed
1501 *      - the error flag is set for the returned value
1502 *
1503 * @return value of the constructed error object
1504 */
1505jerry_value_t
1506jerry_create_error_sz (jerry_error_t error_type, /**< type of error */
1507                       const jerry_char_t *message_p, /**< value of 'message' property
1508                                                       *   of constructed error object */
1509                       jerry_size_t message_size) /**< size of the message in bytes */
1510{
1511  jerry_assert_api_available ();
1512
1513  if (message_p == NULL || message_size == 0)
1514  {
1515    return ecma_create_error_object_reference (ecma_new_standard_error ((ecma_standard_error_t) error_type));
1516  }
1517  else
1518  {
1519    ecma_string_t *message_string_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) message_p,
1520                                                                      (lit_utf8_size_t) message_size);
1521
1522    ecma_object_t *error_object_p = ecma_new_standard_error_with_message ((ecma_standard_error_t) error_type,
1523                                                                          message_string_p);
1524
1525    ecma_deref_ecma_string (message_string_p);
1526
1527    return ecma_create_error_object_reference (error_object_p);
1528  }
1529} /* jerry_create_error_sz */
1530
1531/**
1532 * Create an external function object
1533 *
1534 * Note:
1535 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1536 *
1537 * @return value of the constructed function object
1538 */
1539jerry_value_t
1540jerry_create_external_function (jerry_external_handler_t handler_p) /**< pointer to native handler
1541                                                                     *   for the function */
1542{
1543  jerry_assert_api_available ();
1544
1545  ecma_object_t *func_obj_p = ecma_op_create_external_function_object (handler_p);
1546  return ecma_make_object_value (func_obj_p);
1547} /* jerry_create_external_function */
1548
1549/**
1550 * Creates a jerry_value_t representing a number value.
1551 *
1552 * Note:
1553 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1554 *
1555 * @return jerry_value_t created from the given double argument.
1556 */
1557jerry_value_t
1558jerry_create_number (double value) /**< double value from which a jerry_value_t will be created */
1559{
1560  jerry_assert_api_available ();
1561
1562  return ecma_make_number_value ((ecma_number_t) value);
1563} /* jerry_create_number */
1564
1565/**
1566 * Creates a jerry_value_t representing a positive or negative infinity value.
1567 *
1568 * Note:
1569 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1570 *
1571 * @return jerry_value_t representing an infinity value.
1572 */
1573jerry_value_t
1574jerry_create_number_infinity (bool sign) /**< true for negative Infinity
1575                                          *   false for positive Infinity */
1576{
1577  jerry_assert_api_available ();
1578
1579  return ecma_make_number_value (ecma_number_make_infinity (sign));
1580} /* jerry_create_number_infinity */
1581
1582/**
1583 * Creates a jerry_value_t representing a not-a-number value.
1584 *
1585 * Note:
1586 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1587 *
1588 * @return jerry_value_t representing a not-a-number value.
1589 */
1590jerry_value_t
1591jerry_create_number_nan (void)
1592{
1593  jerry_assert_api_available ();
1594
1595  return ecma_make_nan_value ();
1596} /* jerry_create_number_nan */
1597
1598/**
1599 * Creates a jerry_value_t representing an undefined value.
1600 *
1601 * @return value of undefined
1602 */
1603jerry_value_t
1604jerry_create_undefined (void)
1605{
1606  jerry_assert_api_available ();
1607
1608  return ECMA_VALUE_UNDEFINED;
1609} /* jerry_create_undefined */
1610
1611/**
1612 * Creates and returns a jerry_value_t with type null object.
1613 *
1614 * @return jerry_value_t representing null
1615 */
1616jerry_value_t
1617jerry_create_null (void)
1618{
1619  jerry_assert_api_available ();
1620
1621  return ECMA_VALUE_NULL;
1622} /* jerry_create_null */
1623
1624/**
1625 * Create new JavaScript object, like with new Object().
1626 *
1627 * Note:
1628 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1629 *
1630 * @return value of the created object
1631 */
1632jerry_value_t
1633jerry_create_object (void)
1634{
1635  jerry_assert_api_available ();
1636
1637  return ecma_make_object_value (ecma_op_create_object_object_noarg ());
1638} /* jerry_create_object */
1639
1640/**
1641 * Create an empty Promise object which can be resolve/reject later
1642 * by calling jerry_resolve_or_reject_promise.
1643 *
1644 * Note:
1645 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1646 *
1647 * @return value of the created object
1648 */
1649jerry_value_t
1650jerry_create_promise (void)
1651{
1652  jerry_assert_api_available ();
1653
1654#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
1655  ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target);
1656
1657  if (old_new_target_p == NULL)
1658  {
1659    JERRY_CONTEXT (current_new_target) = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE);
1660  }
1661
1662  ecma_value_t promise_value = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_PROMISE_EXECUTOR_EMPTY);
1663
1664  JERRY_CONTEXT (current_new_target) = old_new_target_p;
1665  return promise_value;
1666#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
1667  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
1668#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
1669} /* jerry_create_promise */
1670
1671/**
1672 * Create a new Proxy object with the given target and handler
1673 *
1674 * Note:
1675 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1676 *
1677 * @return value of the created Proxy object
1678 */
1679jerry_value_t
1680jerry_create_proxy (const jerry_value_t target, /**< target argument */
1681                    const jerry_value_t handler) /**< handler argument */
1682{
1683  jerry_assert_api_available ();
1684
1685  if (ecma_is_value_error_reference (target)
1686      || ecma_is_value_error_reference (handler))
1687  {
1688    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
1689  }
1690
1691#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
1692  ecma_object_t *proxy_p = ecma_proxy_create (target, handler);
1693  return jerry_return (proxy_p == NULL ? ECMA_VALUE_ERROR : ecma_make_object_value (proxy_p));
1694#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
1695  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Proxy is not supported.")));
1696#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
1697} /* jerry_create_proxy */
1698
1699/**
1700 * Create string from a valid UTF-8 string
1701 *
1702 * Note:
1703 *      returned value must be freed with jerry_release_value when it is no longer needed.
1704 *
1705 * @return value of the created string
1706 */
1707jerry_value_t
1708jerry_create_string_from_utf8 (const jerry_char_t *str_p) /**< pointer to string */
1709{
1710  return jerry_create_string_sz_from_utf8 (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p));
1711} /* jerry_create_string_from_utf8 */
1712
1713/**
1714 * Create string from a valid UTF-8 string
1715 *
1716 * Note:
1717 *      returned value must be freed with jerry_release_value when it is no longer needed.
1718 *
1719 * @return value of the created string
1720 */
1721jerry_value_t
1722jerry_create_string_sz_from_utf8 (const jerry_char_t *str_p, /**< pointer to string */
1723                                  jerry_size_t str_size) /**< string size */
1724{
1725  jerry_assert_api_available ();
1726
1727  ecma_string_t *ecma_str_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 ((lit_utf8_byte_t *) str_p,
1728                                                                                 (lit_utf8_size_t) str_size);
1729
1730  return ecma_make_string_value (ecma_str_p);
1731} /* jerry_create_string_sz_from_utf8 */
1732
1733/**
1734 * Create string from a valid CESU-8 string
1735 *
1736 * Note:
1737 *      returned value must be freed with jerry_release_value, when it is no longer needed.
1738 *
1739 * @return value of the created string
1740 */
1741jerry_value_t
1742jerry_create_string (const jerry_char_t *str_p) /**< pointer to string */
1743{
1744  return jerry_create_string_sz (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p));
1745} /* jerry_create_string */
1746
1747/**
1748 * Create string from a valid CESU-8 string
1749 *
1750 * Note:
1751 *      returned value must be freed with jerry_release_value when it is no longer needed.
1752 *
1753 * @return value of the created string
1754 */
1755jerry_value_t
1756jerry_create_string_sz (const jerry_char_t *str_p, /**< pointer to string */
1757                        jerry_size_t str_size) /**< string size */
1758{
1759  jerry_assert_api_available ();
1760
1761  ecma_string_t *ecma_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) str_p,
1762                                                              (lit_utf8_size_t) str_size);
1763  return ecma_make_string_value (ecma_str_p);
1764} /* jerry_create_string_sz */
1765
1766/**
1767 * Create symbol from an api value
1768 *
1769 * Note:
1770 *      The given argument is converted to string. This operation can throw an error.
1771 *      returned value must be freed with jerry_release_value when it is no longer needed.
1772 *
1773 * @return value of the created symbol, if success
1774 *         thrown error, otherwise
1775 */
1776jerry_value_t
1777jerry_create_symbol (const jerry_value_t value) /**< api value */
1778{
1779  jerry_assert_api_available ();
1780
1781  if (ecma_is_value_error_reference (value))
1782  {
1783    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
1784  }
1785
1786#if ENABLED (JERRY_ES2015)
1787  return jerry_return (ecma_op_create_symbol (&value, 1));
1788#else /* !ENABLED (JERRY_ES2015) */
1789  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported.")));
1790#endif /* ENABLED (JERRY_ES2015) */
1791} /* jerry_create_symbol */
1792
1793/**
1794 * Calculates the size of the given pattern and creates a RegExp object.
1795 *
1796 * @return value of the constructed RegExp object.
1797 */
1798jerry_value_t
1799jerry_create_regexp (const jerry_char_t *pattern_p, /**< zero-terminated UTF-8 string as RegExp pattern */
1800                     uint16_t flags) /**< optional RegExp flags */
1801{
1802  return jerry_create_regexp_sz (pattern_p, lit_zt_utf8_string_size (pattern_p), flags);
1803} /* jerry_create_regexp */
1804
1805/**
1806 * Creates a RegExp object with the given pattern and flags.
1807 *
1808 * @return value of the constructed RegExp object.
1809 */
1810jerry_value_t
1811jerry_create_regexp_sz (const jerry_char_t *pattern_p, /**< zero-terminated UTF-8 string as RegExp pattern */
1812                        jerry_size_t pattern_size, /**< length of the pattern */
1813                        uint16_t flags) /**< optional RegExp flags */
1814{
1815  jerry_assert_api_available ();
1816
1817#if ENABLED (JERRY_BUILTIN_REGEXP)
1818  if (!lit_is_valid_utf8_string (pattern_p, pattern_size))
1819  {
1820    return jerry_throw (ecma_raise_common_error (ECMA_ERR_MSG ("Input must be a valid utf8 string")));
1821  }
1822
1823  ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL);
1824
1825  if (JERRY_UNLIKELY (regexp_obj_p == NULL))
1826  {
1827    return ECMA_VALUE_ERROR;
1828  }
1829
1830  ecma_string_t *ecma_pattern = ecma_new_ecma_string_from_utf8 (pattern_p, pattern_size);
1831
1832  jerry_value_t ret_val = ecma_op_create_regexp_with_flags (regexp_obj_p,
1833                                                            ecma_make_string_value (ecma_pattern),
1834                                                            flags);
1835  ecma_deref_ecma_string (ecma_pattern);
1836
1837  return ret_val;
1838
1839#else /* !ENABLED (JERRY_BUILTIN_REGEXP) */
1840  JERRY_UNUSED (pattern_p);
1841  JERRY_UNUSED (pattern_size);
1842  JERRY_UNUSED (flags);
1843
1844  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("RegExp is not supported.")));
1845#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
1846} /* jerry_create_regexp_sz */
1847
1848/**
1849 * Get length of an array object
1850 *
1851 * Note:
1852 *      Returns 0, if the value parameter is not an array object.
1853 *
1854 * @return length of the given array
1855 */
1856uint32_t
1857jerry_get_array_length (const jerry_value_t value) /**< api value */
1858{
1859  jerry_assert_api_available ();
1860
1861  if (!jerry_value_is_object (value))
1862  {
1863    return 0;
1864  }
1865
1866  ecma_object_t *object_p = ecma_get_object_from_value (value);
1867
1868  if (JERRY_LIKELY (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY))
1869  {
1870    return ecma_array_get_length (object_p);
1871  }
1872
1873  return 0;
1874} /* jerry_get_array_length */
1875
1876/**
1877 * Get size of Jerry string
1878 *
1879 * Note:
1880 *      Returns 0, if the value parameter is not a string.
1881 *
1882 * @return number of bytes in the buffer needed to represent the string
1883 */
1884jerry_size_t
1885jerry_get_string_size (const jerry_value_t value) /**< input string */
1886{
1887  jerry_assert_api_available ();
1888
1889  if (!ecma_is_value_string (value))
1890  {
1891    return 0;
1892  }
1893
1894  return ecma_string_get_size (ecma_get_string_from_value (value));
1895} /* jerry_get_string_size */
1896
1897/**
1898 * Get UTF-8 encoded string size from Jerry string
1899 *
1900 * Note:
1901 *      Returns 0, if the value parameter is not a string.
1902 *
1903 * @return number of bytes in the buffer needed to represent the UTF-8 encoded string
1904 */
1905jerry_size_t
1906jerry_get_utf8_string_size (const jerry_value_t value) /**< input string */
1907{
1908  jerry_assert_api_available ();
1909
1910  if (!ecma_is_value_string (value))
1911  {
1912    return 0;
1913  }
1914
1915  return ecma_string_get_utf8_size (ecma_get_string_from_value (value));
1916} /* jerry_get_utf8_string_size */
1917
1918/**
1919 * Get length of Jerry string
1920 *
1921 * Note:
1922 *      Returns 0, if the value parameter is not a string.
1923 *
1924 * @return number of characters in the string
1925 */
1926jerry_length_t
1927jerry_get_string_length (const jerry_value_t value) /**< input string */
1928{
1929  jerry_assert_api_available ();
1930
1931  if (!ecma_is_value_string (value))
1932  {
1933    return 0;
1934  }
1935
1936  return ecma_string_get_length (ecma_get_string_from_value (value));
1937} /* jerry_get_string_length */
1938
1939/**
1940 * Get UTF-8 string length from Jerry string
1941 *
1942 * Note:
1943 *      Returns 0, if the value parameter is not a string.
1944 *
1945 * @return number of characters in the string
1946 */
1947jerry_length_t
1948jerry_get_utf8_string_length (const jerry_value_t value) /**< input string */
1949{
1950  jerry_assert_api_available ();
1951
1952  if (!ecma_is_value_string (value))
1953  {
1954    return 0;
1955  }
1956
1957  return ecma_string_get_utf8_length (ecma_get_string_from_value (value));
1958} /* jerry_get_utf8_string_length */
1959
1960/**
1961 * Copy the characters of a string into a specified buffer.
1962 *
1963 * Note:
1964 *      The '\0' character could occur in character buffer.
1965 *      Returns 0, if the value parameter is not a string or
1966 *      the buffer is not large enough for the whole string.
1967 *
1968 * Note:
1969 *      If the size of the string in jerry value is larger than the size of the
1970 *      target buffer, the copy will fail.
1971 *      To copy substring use jerry_substring_to_char_buffer() instead.
1972 *
1973 * @return number of bytes, actually copied to the buffer.
1974 */
1975jerry_size_t
1976jerry_string_to_char_buffer (const jerry_value_t value, /**< input string value */
1977                             jerry_char_t *buffer_p, /**< [out] output characters buffer */
1978                             jerry_size_t buffer_size) /**< size of output buffer */
1979{
1980  jerry_assert_api_available ();
1981
1982  if (!ecma_is_value_string (value) || buffer_p == NULL)
1983  {
1984    return 0;
1985  }
1986
1987  ecma_string_t *str_p = ecma_get_string_from_value (value);
1988
1989  if (ecma_string_get_size (str_p) > buffer_size)
1990  {
1991    return 0;
1992  }
1993
1994  return ecma_string_copy_to_cesu8_buffer (str_p,
1995                                           (lit_utf8_byte_t *) buffer_p,
1996                                           buffer_size);
1997} /* jerry_string_to_char_buffer */
1998
1999/**
2000 * Copy the characters of an utf-8 encoded string into a specified buffer.
2001 *
2002 * Note:
2003 *      The '\0' character could occur anywhere in the returned string
2004 *      Returns 0, if the value parameter is not a string or the buffer
2005 *      is not large enough for the whole string.
2006 *
2007 * Note:
2008 *      If the size of the string in jerry value is larger than the size of the
2009 *      target buffer, the copy will fail.
2010 *      To copy a substring use jerry_substring_to_utf8_char_buffer() instead.
2011 *
2012 * @return number of bytes copied to the buffer.
2013 */
2014jerry_size_t
2015jerry_string_to_utf8_char_buffer (const jerry_value_t value, /**< input string value */
2016                                  jerry_char_t *buffer_p, /**< [out] output characters buffer */
2017                                  jerry_size_t buffer_size) /**< size of output buffer */
2018{
2019  jerry_assert_api_available ();
2020
2021  if (!ecma_is_value_string (value) || buffer_p == NULL)
2022  {
2023    return 0;
2024  }
2025
2026  ecma_string_t *str_p = ecma_get_string_from_value (value);
2027
2028  if (ecma_string_get_utf8_size (str_p) > buffer_size)
2029  {
2030    return 0;
2031  }
2032
2033  return ecma_string_copy_to_utf8_buffer (str_p,
2034                                          (lit_utf8_byte_t *) buffer_p,
2035                                          buffer_size);
2036} /* jerry_string_to_utf8_char_buffer */
2037
2038/**
2039 * Copy the characters of an cesu-8 encoded substring into a specified buffer.
2040 *
2041 * Note:
2042 *      The '\0' character could occur anywhere in the returned string
2043 *      Returns 0, if the value parameter is not a string.
2044 *      It will extract the substring beetween the specified start position
2045 *      and the end position (or the end of the string, whichever comes first).
2046 *
2047 * @return number of bytes copied to the buffer.
2048 */
2049jerry_size_t
2050jerry_substring_to_char_buffer (const jerry_value_t value, /**< input string value */
2051                                jerry_length_t start_pos, /**< position of the first character */
2052                                jerry_length_t end_pos, /**< position of the last character */
2053                                jerry_char_t *buffer_p, /**< [out] output characters buffer */
2054                                jerry_size_t buffer_size) /**< size of output buffer */
2055{
2056  jerry_assert_api_available ();
2057
2058  if (!ecma_is_value_string (value) || buffer_p == NULL)
2059  {
2060    return 0;
2061  }
2062
2063  ecma_string_t *str_p = ecma_get_string_from_value (value);
2064
2065  return ecma_substring_copy_to_cesu8_buffer (str_p,
2066                                              start_pos,
2067                                              end_pos,
2068                                              (lit_utf8_byte_t *) buffer_p,
2069                                              buffer_size);
2070} /* jerry_substring_to_char_buffer */
2071
2072/**
2073 * Copy the characters of an utf-8 encoded substring into a specified buffer.
2074 *
2075 * Note:
2076 *      The '\0' character could occur anywhere in the returned string
2077 *      Returns 0, if the value parameter is not a string.
2078 *      It will extract the substring beetween the specified start position
2079 *      and the end position (or the end of the string, whichever comes first).
2080 *
2081 * @return number of bytes copied to the buffer.
2082 */
2083jerry_size_t
2084jerry_substring_to_utf8_char_buffer (const jerry_value_t value, /**< input string value */
2085                                     jerry_length_t start_pos, /**< position of the first character */
2086                                     jerry_length_t end_pos, /**< position of the last character */
2087                                     jerry_char_t *buffer_p, /**< [out] output characters buffer */
2088                                     jerry_size_t buffer_size) /**< size of output buffer */
2089{
2090  jerry_assert_api_available ();
2091
2092  if (!ecma_is_value_string (value) || buffer_p == NULL)
2093  {
2094    return 0;
2095  }
2096
2097  ecma_string_t *str_p = ecma_get_string_from_value (value);
2098
2099  return ecma_substring_copy_to_utf8_buffer (str_p,
2100                                             start_pos,
2101                                             end_pos,
2102                                             (lit_utf8_byte_t *) buffer_p,
2103                                             buffer_size);
2104} /* jerry_substring_to_utf8_char_buffer */
2105
2106/**
2107 * Checks whether the object or it's prototype objects have the given property.
2108 *
2109 * @return raised error - if the operation fail
2110 *         true/false API value  - depend on whether the property exists
2111 */
2112jerry_value_t
2113jerry_has_property (const jerry_value_t obj_val, /**< object value */
2114                    const jerry_value_t prop_name_val) /**< property name (string value) */
2115{
2116  jerry_assert_api_available ();
2117
2118  if (!ecma_is_value_object (obj_val)
2119      || !ecma_is_value_prop_name (prop_name_val))
2120  {
2121    return ECMA_VALUE_FALSE;
2122  }
2123
2124  return ecma_op_object_has_property (ecma_get_object_from_value (obj_val),
2125                                      ecma_get_prop_name_from_value (prop_name_val));
2126} /* jerry_has_property */
2127
2128/**
2129 * Checks whether the object has the given property.
2130 *
2131 * @return ECMA_VALUE_ERROR - if the operation raises error
2132 *         ECMA_VALUE_{TRUE, FALSE} - based on whether the property exists
2133 */
2134jerry_value_t
2135jerry_has_own_property (const jerry_value_t obj_val, /**< object value */
2136                        const jerry_value_t prop_name_val) /**< property name (string value) */
2137{
2138  jerry_assert_api_available ();
2139
2140  if (!ecma_is_value_object (obj_val)
2141      || !ecma_is_value_prop_name (prop_name_val))
2142  {
2143    return ECMA_VALUE_FALSE;
2144  }
2145
2146  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2147  ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (prop_name_val);
2148
2149#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
2150  if (ECMA_OBJECT_IS_PROXY (obj_p))
2151  {
2152    ecma_property_descriptor_t prop_desc;
2153
2154    ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc);
2155
2156    if (ecma_is_value_true (status))
2157    {
2158      ecma_free_property_descriptor (&prop_desc);
2159    }
2160
2161    return jerry_return (status);
2162  }
2163#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
2164
2165  return ecma_make_boolean_value (ecma_op_ordinary_object_has_own_property (obj_p, prop_name_p));
2166} /* jerry_has_own_property */
2167
2168/**
2169 * Checks whether the object has the given internal property.
2170 *
2171 * @return true  - if the internal property exists
2172 *         false - otherwise
2173 */
2174bool
2175jerry_has_internal_property (const jerry_value_t obj_val, /**< object value */
2176                             const jerry_value_t prop_name_val) /**< property name value */
2177{
2178  jerry_assert_api_available ();
2179
2180  if (!ecma_is_value_object (obj_val)
2181      || !ecma_is_value_prop_name (prop_name_val))
2182  {
2183    return false;
2184  }
2185
2186  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2187
2188  ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
2189
2190  if (ecma_op_object_is_fast_array (obj_p))
2191  {
2192    return false;
2193  }
2194
2195  ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
2196
2197  if (property_p == NULL)
2198  {
2199    return false;
2200  }
2201
2202  ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
2203  property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (prop_name_val));
2204
2205  return property_p != NULL;
2206} /* jerry_has_internal_property */
2207
2208/**
2209 * Delete a property from an object.
2210 *
2211 * @return true  - if property was deleted successfully
2212 *         false - otherwise
2213 */
2214bool
2215jerry_delete_property (const jerry_value_t obj_val, /**< object value */
2216                       const jerry_value_t prop_name_val) /**< property name (string value) */
2217{
2218  jerry_assert_api_available ();
2219
2220  if (!ecma_is_value_object (obj_val)
2221      || !ecma_is_value_prop_name (prop_name_val))
2222  {
2223    return false;
2224  }
2225
2226  ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val),
2227                                                  ecma_get_prop_name_from_value (prop_name_val),
2228                                                  false);
2229
2230#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
2231  if (ECMA_IS_VALUE_ERROR (ret_value))
2232  {
2233    // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
2234    jcontext_release_exception ();
2235  }
2236#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
2237
2238  return ecma_is_value_true (ret_value);
2239} /* jerry_delete_property */
2240
2241/**
2242 * Delete indexed property from the specified object.
2243 *
2244 * @return true  - if property was deleted successfully
2245 *         false - otherwise
2246 */
2247bool
2248jerry_delete_property_by_index (const jerry_value_t obj_val, /**< object value */
2249                                uint32_t index) /**< index to be written */
2250{
2251  jerry_assert_api_available ();
2252
2253  if (!ecma_is_value_object (obj_val))
2254  {
2255    return false;
2256  }
2257
2258  ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index);
2259  ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val),
2260                                                  str_idx_p,
2261                                                  false);
2262  ecma_deref_ecma_string (str_idx_p);
2263
2264#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
2265  if (ECMA_IS_VALUE_ERROR (ret_value))
2266  {
2267    // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
2268    jcontext_release_exception ();
2269  }
2270#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
2271
2272  return ecma_is_value_true (ret_value);
2273} /* jerry_delete_property_by_index */
2274
2275/**
2276 * Delete an internal property from an object.
2277 *
2278 * @return true  - if property was deleted successfully
2279 *         false - otherwise
2280 */
2281bool
2282jerry_delete_internal_property (const jerry_value_t obj_val, /**< object value */
2283                                const jerry_value_t prop_name_val) /**< property name value */
2284{
2285  jerry_assert_api_available ();
2286
2287  if (!ecma_is_value_object (obj_val)
2288      || !ecma_is_value_prop_name (prop_name_val))
2289  {
2290    return false;
2291  }
2292
2293  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2294
2295  ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
2296
2297  if (ecma_op_object_is_fast_array (obj_p))
2298  {
2299    return true;
2300  }
2301
2302  ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
2303
2304  if (property_p == NULL)
2305  {
2306    return true;
2307  }
2308
2309  ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
2310  property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (prop_name_val));
2311
2312  if (property_p == NULL)
2313  {
2314    return true;
2315  }
2316
2317  ecma_delete_property (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p));
2318
2319  return true;
2320} /* jerry_delete_internal_property */
2321
2322/**
2323 * Get value of a property to the specified object with the given name.
2324 *
2325 * Note:
2326 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2327 *
2328 * @return value of the property - if success
2329 *         value marked with error flag - otherwise
2330 */
2331jerry_value_t
2332jerry_get_property (const jerry_value_t obj_val, /**< object value */
2333                    const jerry_value_t prop_name_val) /**< property name (string value) */
2334{
2335  jerry_assert_api_available ();
2336
2337  if (!ecma_is_value_object (obj_val)
2338      || !ecma_is_value_prop_name (prop_name_val))
2339  {
2340    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2341  }
2342
2343  jerry_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_val),
2344                                                ecma_get_prop_name_from_value (prop_name_val));
2345  return jerry_return (ret_value);
2346} /* jerry_get_property */
2347
2348/**
2349 * Get value by an index from the specified object.
2350 *
2351 * Note:
2352 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2353 *
2354 * @return value of the property specified by the index - if success
2355 *         value marked with error flag - otherwise
2356 */
2357jerry_value_t
2358jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */
2359                             uint32_t index) /**< index to be written */
2360{
2361  jerry_assert_api_available ();
2362
2363  if (!ecma_is_value_object (obj_val))
2364  {
2365    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2366  }
2367
2368  ecma_value_t ret_value = ecma_op_object_get_by_uint32_index (ecma_get_object_from_value (obj_val), index);
2369
2370  return jerry_return (ret_value);
2371} /* jerry_get_property_by_index */
2372
2373/**
2374 * Get value of an internal property to the specified object with the given name.
2375 *
2376 * Note:
2377 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2378 *
2379 * @return value of the internal property - if the internal property exists
2380 *         undefined value - if the internal does not property exists
2381 *         value marked with error flag - otherwise
2382 */
2383jerry_value_t
2384jerry_get_internal_property (const jerry_value_t obj_val, /**< object value */
2385                             const jerry_value_t prop_name_val) /**< property name value */
2386{
2387  jerry_assert_api_available ();
2388
2389  if (!ecma_is_value_object (obj_val)
2390      || !ecma_is_value_prop_name (prop_name_val))
2391  {
2392    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2393  }
2394
2395  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2396
2397  ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
2398
2399  if (ecma_op_object_is_fast_array (obj_p))
2400  {
2401    return jerry_return (ECMA_VALUE_UNDEFINED);
2402  }
2403
2404  ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
2405
2406  if (property_p == NULL)
2407  {
2408    return jerry_return (ECMA_VALUE_UNDEFINED);
2409  }
2410
2411  ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
2412  property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (prop_name_val));
2413
2414  if (property_p == NULL)
2415  {
2416    return jerry_return (ECMA_VALUE_UNDEFINED);
2417  }
2418
2419  return jerry_return (ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value));
2420} /* jerry_get_internal_property */
2421
2422/**
2423 * Set a property to the specified object with the given name.
2424 *
2425 * Note:
2426 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2427 *
2428 * @return true value - if the operation was successful
2429 *         value marked with error flag - otherwise
2430 */
2431jerry_value_t
2432jerry_set_property (const jerry_value_t obj_val, /**< object value */
2433                    const jerry_value_t prop_name_val, /**< property name (string value) */
2434                    const jerry_value_t value_to_set) /**< value to set */
2435{
2436  jerry_assert_api_available ();
2437
2438  if (ecma_is_value_error_reference (value_to_set)
2439      || !ecma_is_value_object (obj_val)
2440      || !ecma_is_value_prop_name (prop_name_val))
2441  {
2442    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2443  }
2444
2445  return jerry_return (ecma_op_object_put (ecma_get_object_from_value (obj_val),
2446                                           ecma_get_prop_name_from_value (prop_name_val),
2447                                           value_to_set,
2448                                           true));
2449} /* jerry_set_property */
2450
2451/**
2452 * Set indexed value in the specified object
2453 *
2454 * Note:
2455 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2456 *
2457 * @return true value - if the operation was successful
2458 *         value marked with error flag - otherwise
2459 */
2460jerry_value_t
2461jerry_set_property_by_index (const jerry_value_t obj_val, /**< object value */
2462                             uint32_t index, /**< index to be written */
2463                             const jerry_value_t value_to_set) /**< value to set */
2464{
2465  jerry_assert_api_available ();
2466
2467  if (ecma_is_value_error_reference (value_to_set)
2468      || !ecma_is_value_object (obj_val))
2469  {
2470    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2471  }
2472
2473  ecma_value_t ret_value = ecma_op_object_put_by_uint32_index (ecma_get_object_from_value (obj_val),
2474                                                               index,
2475                                                               value_to_set,
2476                                                               true);
2477
2478  return jerry_return (ret_value);
2479} /* jerry_set_property_by_index */
2480
2481/**
2482 * Set an internal property to the specified object with the given name.
2483 *
2484 * Note:
2485 *      - the property cannot be accessed from the JavaScript context, only from the public API
2486 *      - returned value must be freed with jerry_release_value, when it is no longer needed.
2487 *
2488 * @return true value - if the operation was successful
2489 *         value marked with error flag - otherwise
2490 */
2491bool
2492jerry_set_internal_property (const jerry_value_t obj_val, /**< object value */
2493                             const jerry_value_t prop_name_val, /**< property name value */
2494                             const jerry_value_t value_to_set) /**< value to set */
2495{
2496  jerry_assert_api_available ();
2497
2498  if (ecma_is_value_error_reference (value_to_set)
2499      || !ecma_is_value_object (obj_val)
2500      || !ecma_is_value_prop_name (prop_name_val))
2501  {
2502    return false;
2503  }
2504
2505  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2506
2507  ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL);
2508
2509  if (ecma_op_object_is_fast_array (obj_p))
2510  {
2511    ecma_fast_array_convert_to_normal (obj_p);
2512  }
2513
2514  ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p);
2515  ecma_object_t *internal_object_p;
2516
2517  if (property_p == NULL)
2518  {
2519    ecma_property_value_t *value_p = ecma_create_named_data_property (obj_p,
2520                                                                      internal_string_p,
2521                                                                      ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
2522                                                                      NULL);
2523
2524    internal_object_p = ecma_create_object (NULL,
2525                                            sizeof (ecma_extended_object_t),
2526                                            ECMA_OBJECT_TYPE_CLASS);
2527    {
2528      ecma_extended_object_t *container_p = (ecma_extended_object_t *) internal_object_p;
2529      container_p->u.class_prop.class_id = LIT_INTERNAL_MAGIC_STRING_INTERNAL_OBJECT;
2530      container_p->u.class_prop.extra_info = 0;
2531      container_p->u.class_prop.u.length = 0;
2532    }
2533
2534    value_p->value = ecma_make_object_value (internal_object_p);
2535    ecma_deref_object (internal_object_p);
2536  }
2537  else
2538  {
2539    internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
2540  }
2541
2542  ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (prop_name_val);
2543  property_p = ecma_find_named_property (internal_object_p, prop_name_p);
2544
2545  if (property_p == NULL)
2546  {
2547    ecma_property_value_t *value_p = ecma_create_named_data_property (internal_object_p,
2548                                                                      prop_name_p,
2549                                                                      ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
2550                                                                      NULL);
2551
2552    value_p->value = ecma_copy_value_if_not_object (value_to_set);
2553  }
2554  else
2555  {
2556    ecma_named_data_property_assign_value (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value_to_set);
2557  }
2558
2559  return true;
2560} /* jerry_set_internal_property */
2561
2562/**
2563 * Initialize property descriptor.
2564 */
2565void
2566jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p) /**< [out] property descriptor */
2567{
2568  prop_desc_p->is_value_defined = false;
2569  prop_desc_p->value = ECMA_VALUE_UNDEFINED;
2570  prop_desc_p->is_writable_defined = false;
2571  prop_desc_p->is_writable = false;
2572  prop_desc_p->is_enumerable_defined = false;
2573  prop_desc_p->is_enumerable = false;
2574  prop_desc_p->is_configurable_defined = false;
2575  prop_desc_p->is_configurable = false;
2576  prop_desc_p->is_get_defined = false;
2577  prop_desc_p->getter = ECMA_VALUE_UNDEFINED;
2578  prop_desc_p->is_set_defined = false;
2579  prop_desc_p->setter = ECMA_VALUE_UNDEFINED;
2580} /* jerry_init_property_descriptor_fields */
2581
2582/**
2583 * Define a property to the specified object with the given name.
2584 *
2585 * Note:
2586 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2587 *
2588 * @return true value - if the operation was successful
2589 *         value marked with error flag - otherwise
2590 */
2591jerry_value_t
2592jerry_define_own_property (const jerry_value_t obj_val, /**< object value */
2593                           const jerry_value_t prop_name_val, /**< property name (string value) */
2594                           const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */
2595{
2596  jerry_assert_api_available ();
2597
2598  if (!ecma_is_value_object (obj_val)
2599      || !ecma_is_value_prop_name (prop_name_val))
2600  {
2601    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2602  }
2603
2604  if ((prop_desc_p->is_writable_defined || prop_desc_p->is_value_defined)
2605      && (prop_desc_p->is_get_defined || prop_desc_p->is_set_defined))
2606  {
2607    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2608  }
2609
2610  ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
2611
2612  uint32_t flags = ECMA_PROP_NO_OPTS;
2613
2614  if (prop_desc_p->is_enumerable_defined)
2615  {
2616    flags |= (uint32_t) (ECMA_PROP_IS_ENUMERABLE_DEFINED | (prop_desc_p->is_enumerable ? ECMA_PROP_IS_ENUMERABLE
2617                                                                                       : ECMA_PROP_NO_OPTS));
2618  }
2619
2620  if (prop_desc_p->is_configurable_defined)
2621  {
2622    flags |= (uint32_t) (ECMA_PROP_IS_CONFIGURABLE_DEFINED | (prop_desc_p->is_configurable ? ECMA_PROP_IS_CONFIGURABLE
2623                                                                                           : ECMA_PROP_NO_OPTS));
2624  }
2625
2626  /* Copy data property info. */
2627  flags |= (prop_desc_p->is_value_defined ? ECMA_PROP_IS_VALUE_DEFINED : ECMA_PROP_NO_OPTS);
2628
2629  if (prop_desc_p->is_value_defined)
2630  {
2631    if (ecma_is_value_error_reference (prop_desc_p->value))
2632    {
2633      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2634    }
2635
2636    prop_desc.value = prop_desc_p->value;
2637  }
2638
2639  if (prop_desc_p->is_writable_defined)
2640  {
2641    flags |= (uint32_t) (ECMA_PROP_IS_WRITABLE_DEFINED | (prop_desc_p->is_writable ? ECMA_PROP_IS_WRITABLE
2642                                                                                   : ECMA_PROP_NO_OPTS));
2643  }
2644
2645  /* Copy accessor property info. */
2646  if (prop_desc_p->is_get_defined)
2647  {
2648    ecma_value_t getter = prop_desc_p->getter;
2649    flags |= ECMA_PROP_IS_GET_DEFINED;
2650
2651    if (ecma_is_value_error_reference (getter))
2652    {
2653      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2654    }
2655
2656    if (ecma_op_is_callable (getter))
2657    {
2658      prop_desc.get_p = ecma_get_object_from_value (getter);
2659    }
2660    else if (!ecma_is_value_null (getter))
2661    {
2662      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2663    }
2664  }
2665
2666  if (prop_desc_p->is_set_defined)
2667  {
2668    ecma_value_t setter = prop_desc_p->setter;
2669    flags |= ECMA_PROP_IS_SET_DEFINED;
2670
2671    if (ecma_is_value_error_reference (setter))
2672    {
2673      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2674    }
2675
2676    if (ecma_op_is_callable (setter))
2677    {
2678      prop_desc.set_p = ecma_get_object_from_value (setter);
2679    }
2680    else if (!ecma_is_value_null (setter))
2681    {
2682      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2683    }
2684  }
2685
2686  prop_desc.flags |= (uint16_t) (flags | ECMA_PROP_IS_THROW);
2687
2688  return ecma_op_object_define_own_property (ecma_get_object_from_value (obj_val),
2689                                             ecma_get_prop_name_from_value (prop_name_val),
2690                                             &prop_desc);
2691} /* jerry_define_own_property */
2692
2693/**
2694 * Construct property descriptor from specified property.
2695 *
2696 * @return true - if success, the prop_desc_p fields contains the property info
2697 *         false - otherwise, the prop_desc_p is unchanged
2698 */
2699bool
2700jerry_get_own_property_descriptor (const jerry_value_t  obj_val, /**< object value */
2701                                   const jerry_value_t prop_name_val, /**< property name (string value) */
2702                                   jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */
2703{
2704  jerry_assert_api_available ();
2705
2706  if (!ecma_is_value_object (obj_val)
2707      || !ecma_is_value_prop_name (prop_name_val))
2708  {
2709    return false;
2710  }
2711
2712  ecma_property_descriptor_t prop_desc;
2713
2714  ecma_value_t status = ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_val),
2715                                                                    ecma_get_prop_name_from_value (prop_name_val),
2716                                                                    &prop_desc);
2717
2718#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
2719  if (ECMA_IS_VALUE_ERROR (status))
2720  {
2721    // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
2722    jcontext_release_exception ();
2723  }
2724#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
2725
2726  if (!ecma_is_value_true (status))
2727  {
2728    return false;
2729  }
2730
2731  prop_desc_p->is_configurable_defined = true;
2732  prop_desc_p->is_configurable = (prop_desc.flags & ECMA_PROP_IS_CONFIGURABLE) != 0;
2733  prop_desc_p->is_enumerable_defined = true;
2734  prop_desc_p->is_enumerable = (prop_desc.flags & ECMA_PROP_IS_ENUMERABLE) != 0;
2735
2736  prop_desc_p->is_writable_defined = (prop_desc.flags & ECMA_PROP_IS_WRITABLE_DEFINED) != 0;
2737  prop_desc_p->is_writable = prop_desc_p->is_writable_defined ? (prop_desc.flags & ECMA_PROP_IS_WRITABLE) != 0 : false;
2738
2739  prop_desc_p->is_value_defined = (prop_desc.flags & ECMA_PROP_IS_VALUE_DEFINED) != 0;
2740  prop_desc_p->is_get_defined = (prop_desc.flags & ECMA_PROP_IS_GET_DEFINED) != 0;
2741  prop_desc_p->is_set_defined = (prop_desc.flags & ECMA_PROP_IS_SET_DEFINED) != 0;
2742
2743  prop_desc_p->value = ECMA_VALUE_UNDEFINED;
2744  prop_desc_p->getter = ECMA_VALUE_UNDEFINED;
2745  prop_desc_p->setter = ECMA_VALUE_UNDEFINED;
2746
2747  if (prop_desc_p->is_value_defined)
2748  {
2749    prop_desc_p->value = prop_desc.value;
2750  }
2751
2752  if (prop_desc_p->is_get_defined)
2753  {
2754    if (prop_desc.get_p != NULL)
2755    {
2756      prop_desc_p->getter = ecma_make_object_value (prop_desc.get_p);
2757    }
2758    else
2759    {
2760      prop_desc_p->getter = ECMA_VALUE_NULL;
2761    }
2762  }
2763
2764  if (prop_desc_p->is_set_defined)
2765  {
2766    if (prop_desc.set_p != NULL)
2767    {
2768      prop_desc_p->setter = ecma_make_object_value (prop_desc.set_p);
2769    }
2770    else
2771    {
2772      prop_desc_p->setter = ECMA_VALUE_NULL;
2773    }
2774  }
2775
2776  return true;
2777} /* jerry_get_own_property_descriptor */
2778
2779/**
2780 * Free fields of property descriptor (setter, getter and value).
2781 */
2782void
2783jerry_free_property_descriptor_fields (const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */
2784{
2785  if (prop_desc_p->is_value_defined)
2786  {
2787    jerry_release_value (prop_desc_p->value);
2788  }
2789
2790  if (prop_desc_p->is_get_defined)
2791  {
2792    jerry_release_value (prop_desc_p->getter);
2793  }
2794
2795  if (prop_desc_p->is_set_defined)
2796  {
2797    jerry_release_value (prop_desc_p->setter);
2798  }
2799} /* jerry_free_property_descriptor_fields */
2800
2801/**
2802 * Invoke function specified by a function value
2803 *
2804 * Note:
2805 *      - returned value must be freed with jerry_release_value, when it is no longer needed.
2806 *      - If function is invoked as constructor, it should support [[Construct]] method,
2807 *        otherwise, if function is simply called - it should support [[Call]] method.
2808 *
2809 * @return returned jerry value of the invoked function
2810 */
2811static jerry_value_t
2812jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke function as constructor
2813                                                       *          (this_arg_p should be NULL, as it is ignored),
2814                                                       *   false - perform function call */
2815                       const jerry_value_t func_obj_val, /**< function object to call */
2816                       const jerry_value_t this_val, /**< object value of 'this' binding */
2817                       const jerry_value_t args_p[], /**< function's call arguments */
2818                       const jerry_size_t args_count) /**< number of the arguments */
2819{
2820  JERRY_ASSERT (args_count == 0 || args_p != NULL);
2821
2822  if (ecma_is_value_error_reference (func_obj_val)
2823      || ecma_is_value_error_reference (this_val))
2824  {
2825    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
2826  }
2827
2828  for (uint32_t i = 0; i < args_count; i++)
2829  {
2830    if (ecma_is_value_error_reference (args_p[i]))
2831    {
2832      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
2833    }
2834  }
2835
2836  if (is_invoke_as_constructor)
2837  {
2838    JERRY_ASSERT (jerry_value_is_constructor (func_obj_val));
2839
2840    return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_obj_val),
2841                                                     ecma_get_object_from_value (func_obj_val),
2842                                                     args_p,
2843                                                     args_count));
2844  }
2845  else
2846  {
2847    JERRY_ASSERT (jerry_value_is_function (func_obj_val));
2848
2849    return jerry_return (ecma_op_function_call (ecma_get_object_from_value (func_obj_val),
2850                                                this_val,
2851                                                args_p,
2852                                                args_count));
2853  }
2854} /* jerry_invoke_function */
2855
2856/**
2857 * Call function specified by a function value
2858 *
2859 * Note:
2860 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2861 *      error flag must not be set for any arguments of this function.
2862 *
2863 * @return returned jerry value of the called function
2864 */
2865jerry_value_t
2866jerry_call_function (const jerry_value_t func_obj_val, /**< function object to call */
2867                     const jerry_value_t this_val, /**< object for 'this' binding */
2868                     const jerry_value_t args_p[], /**< function's call arguments */
2869                     jerry_size_t args_count) /**< number of the arguments */
2870{
2871  jerry_assert_api_available ();
2872
2873#if ENABLED (JERRY_DEBUGGER)
2874  /**
2875   * Clear flag JERRY_DEBUGGER_VM_STOP and set debugger_stop_context Null everytime jerry's debugger call a function.
2876   * This could solve the problem that jerry's debugger stops at an unexpected line when re-entering a function after a
2877   * step-operation.
2878   */
2879  JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP);
2880  JERRY_CONTEXT (debugger_stop_context) = NULL;
2881
2882  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) {
2883    if (jerry_debugger_receive (NULL)) {
2884      JERRY_DEBUG_MSG ("resume");
2885    }
2886  }
2887#endif
2888
2889  if (jerry_value_is_function (func_obj_val) && !ecma_is_value_error_reference (this_val))
2890  {
2891    for (jerry_size_t i = 0; i < args_count; i++)
2892    {
2893      if (ecma_is_value_error_reference (args_p[i]))
2894      {
2895        return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
2896      }
2897    }
2898
2899    return jerry_invoke_function (false, func_obj_val, this_val, args_p, args_count);
2900  }
2901
2902  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2903} /* jerry_call_function */
2904
2905/**
2906 * Construct object value invoking specified function value as a constructor
2907 *
2908 * Note:
2909 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2910 *      error flag must not be set for any arguments of this function.
2911 *
2912 * @return returned jerry value of the invoked constructor
2913 */
2914jerry_value_t
2915jerry_construct_object (const jerry_value_t func_obj_val, /**< function object to call */
2916                        const jerry_value_t args_p[], /**< function's call arguments
2917                                                       *   (NULL if arguments number is zero) */
2918                        jerry_size_t args_count) /**< number of the arguments */
2919{
2920  jerry_assert_api_available ();
2921
2922  if (jerry_value_is_constructor (func_obj_val))
2923  {
2924    for (jerry_size_t i = 0; i < args_count; i++)
2925    {
2926      if (ecma_is_value_error_reference (args_p[i]))
2927      {
2928        return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
2929      }
2930    }
2931
2932    ecma_value_t this_val = ECMA_VALUE_UNDEFINED;
2933    return jerry_invoke_function (true, func_obj_val, this_val, args_p, args_count);
2934  }
2935
2936  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2937} /* jerry_construct_object */
2938
2939/**
2940 * Get keys of the specified object value
2941 *
2942 * Note:
2943 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2944 *
2945 * @return array object value - if success
2946 *         value marked with error flag - otherwise
2947 */
2948jerry_value_t
2949jerry_get_object_keys (const jerry_value_t obj_val) /**< object value */
2950{
2951  jerry_assert_api_available ();
2952
2953  if (!ecma_is_value_object (obj_val))
2954  {
2955    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2956  }
2957
2958  return ecma_builtin_helper_object_get_properties (ecma_get_object_from_value (obj_val),
2959                                                    ECMA_LIST_ENUMERABLE);
2960} /* jerry_get_object_keys */
2961
2962/**
2963 * Get the prototype of the specified object
2964 *
2965 * Note:
2966 *      returned value must be freed with jerry_release_value, when it is no longer needed.
2967 *
2968 * @return prototype object or null value - if success
2969 *         value marked with error flag - otherwise
2970 */
2971jerry_value_t
2972jerry_get_prototype (const jerry_value_t obj_val) /**< object value */
2973{
2974  jerry_assert_api_available ();
2975
2976  if (!ecma_is_value_object (obj_val))
2977  {
2978    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2979  }
2980
2981  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2982
2983#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
2984  if (ECMA_OBJECT_IS_PROXY (obj_p))
2985  {
2986    return jerry_return (ecma_proxy_object_get_prototype_of (obj_p));
2987  }
2988#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
2989
2990  if (obj_p->u2.prototype_cp == JMEM_CP_NULL)
2991  {
2992    return ECMA_VALUE_NULL;
2993  }
2994
2995  ecma_object_t *proto_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_p->u2.prototype_cp);
2996  ecma_ref_object (proto_obj_p);
2997
2998  return ecma_make_object_value (proto_obj_p);
2999} /* jerry_get_prototype */
3000
3001/**
3002 * Set the prototype of the specified object
3003 *
3004 * @return true value - if success
3005 *         value marked with error flag - otherwise
3006 */
3007jerry_value_t
3008jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
3009                     const jerry_value_t proto_obj_val) /**< prototype object value */
3010{
3011  jerry_assert_api_available ();
3012
3013  if (!ecma_is_value_object (obj_val)
3014      || ecma_is_value_error_reference (proto_obj_val)
3015      || (!ecma_is_value_object (proto_obj_val) && !ecma_is_value_null (proto_obj_val)))
3016  {
3017    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3018  }
3019  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
3020
3021#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
3022  if (ECMA_OBJECT_IS_PROXY (obj_p))
3023  {
3024    return jerry_return (ecma_proxy_object_set_prototype_of (obj_p, proto_obj_val));
3025  }
3026#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
3027
3028  return ecma_op_ordinary_object_set_prototype_of (obj_p, proto_obj_val);
3029} /* jerry_set_prototype */
3030
3031/**
3032 * Utility to check if a given object can be used for the foreach api calls.
3033 *
3034 * Some objects/classes uses extra internal objects to correctly store data.
3035 * These extre object should never be exposed externally to the API user.
3036 *
3037 * @returns true - if the user can access the object in the callback.
3038 *          false - if the object is an internal object which should no be accessed by the user.
3039 */
3040static
3041bool jerry_object_is_valid_foreach (ecma_object_t *object_p) /**< object to test */
3042{
3043  if (ecma_is_lexical_environment (object_p))
3044  {
3045    return false;
3046  }
3047
3048  ecma_object_type_t object_type = ecma_get_object_type (object_p);
3049
3050  if (object_type == ECMA_OBJECT_TYPE_CLASS)
3051  {
3052    ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
3053    switch (ext_object_p->u.class_prop.class_id)
3054    {
3055      /* An object's internal property object should not be iterable by foreach. */
3056      case LIT_INTERNAL_MAGIC_STRING_INTERNAL_OBJECT: return false;
3057    }
3058  }
3059
3060  return true;
3061} /* jerry_object_is_valid_foreach */
3062
3063/**
3064 * Traverse objects.
3065 *
3066 * @return true - traversal was interrupted by the callback.
3067 *         false - otherwise - traversal visited all objects.
3068 */
3069bool
3070jerry_objects_foreach (jerry_objects_foreach_t foreach_p, /**< function pointer of the iterator function */
3071                       void *user_data_p) /**< pointer to user data */
3072{
3073  jerry_assert_api_available ();
3074
3075  JERRY_ASSERT (foreach_p != NULL);
3076
3077  jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp);
3078
3079  while (iter_cp != JMEM_CP_NULL)
3080  {
3081    ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp);
3082
3083    if (jerry_object_is_valid_foreach (iter_p)
3084        && !foreach_p (ecma_make_object_value (iter_p), user_data_p))
3085    {
3086      return true;
3087    }
3088
3089    iter_cp = iter_p->gc_next_cp;
3090  }
3091
3092  return false;
3093} /* jerry_objects_foreach */
3094
3095/**
3096 * Traverse objects having a given native type info.
3097 *
3098 * @return true - traversal was interrupted by the callback.
3099 *         false - otherwise - traversal visited all objects.
3100 */
3101bool
3102jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_info_p, /**< the type info
3103                                                                                        *   of the native pointer */
3104                                      jerry_objects_foreach_by_native_info_t foreach_p, /**< function to apply for
3105                                                                                         *   each matching object */
3106                                      void *user_data_p) /**< pointer to user data */
3107{
3108  jerry_assert_api_available ();
3109
3110  JERRY_ASSERT (native_info_p != NULL);
3111  JERRY_ASSERT (foreach_p != NULL);
3112
3113  ecma_native_pointer_t *native_pointer_p;
3114
3115  jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp);
3116
3117  while (iter_cp != JMEM_CP_NULL)
3118  {
3119    ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp);
3120
3121    if (jerry_object_is_valid_foreach (iter_p))
3122    {
3123      native_pointer_p = ecma_get_native_pointer_value (iter_p, (void *) native_info_p);
3124      if (native_pointer_p
3125          && !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->data_p, user_data_p))
3126      {
3127        return true;
3128      }
3129    }
3130
3131    iter_cp = iter_p->gc_next_cp;
3132  }
3133
3134  return false;
3135} /* jerry_objects_foreach_by_native_info */
3136
3137/**
3138 * Get native pointer and its type information, associated with the given native type info.
3139 *
3140 * Note:
3141 *  If native pointer is present, its type information is returned in out_native_pointer_p
3142 *
3143 * @return true - if there is an associated pointer,
3144 *         false - otherwise
3145 */
3146bool
3147jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get native pointer from */
3148                                 void **out_native_pointer_p, /**< [out] native pointer */
3149                                 const jerry_object_native_info_t *native_info_p) /**< the type info
3150                                                                                   *   of the native pointer */
3151{
3152  jerry_assert_api_available ();
3153
3154  if (!ecma_is_value_object (obj_val))
3155  {
3156    return false;
3157  }
3158
3159  ecma_native_pointer_t *native_pointer_p;
3160  native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val), (void *) native_info_p);
3161
3162  if (native_pointer_p == NULL)
3163  {
3164    return false;
3165  }
3166
3167  if (out_native_pointer_p != NULL)
3168  {
3169    *out_native_pointer_p = native_pointer_p->data_p;
3170  }
3171
3172  return true;
3173} /* jerry_get_object_native_pointer */
3174
3175/**
3176 * Set native pointer and an optional type info for the specified object.
3177 *
3178 *
3179 * Note:
3180 *      If native pointer was already set for the object, its value is updated.
3181 *
3182 * Note:
3183 *      If a non-NULL free callback is specified in the native type info,
3184 *      it will be called by the garbage collector when the object is freed.
3185 *      Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
3186 *      The type info always overwrites the previous value, so passing
3187 *      a NULL value deletes the current type info.
3188 */
3189void
3190jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set native pointer in */
3191                                 void *native_pointer_p, /**< native pointer */
3192                                 const jerry_object_native_info_t *native_info_p) /**< object's native type info */
3193{
3194  jerry_assert_api_available ();
3195
3196  if (ecma_is_value_object (obj_val))
3197  {
3198    ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3199
3200    ecma_create_native_pointer_property (object_p, native_pointer_p, (void *) native_info_p);
3201  }
3202} /* jerry_set_object_native_pointer */
3203
3204/**
3205 * Delete the previously set native pointer by the native type info from the specified object.
3206 *
3207 * Note:
3208 *      If the specified object has no matching native pointer for the given native type info
3209 *      the function has no effect.
3210 *
3211 * Note:
3212 *      This operation cannot throw an exception.
3213 *
3214 * @return true - if the native pointer has been deleted succesfully
3215 *         false - otherwise
3216 */
3217bool
3218jerry_delete_object_native_pointer (const jerry_value_t obj_val, /**< object to delete native pointer from */
3219                                    const jerry_object_native_info_t *native_info_p) /**< object's native type info */
3220{
3221  jerry_assert_api_available ();
3222
3223  if (ecma_is_value_object (obj_val))
3224  {
3225    ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3226
3227    return ecma_delete_native_pointer_property (object_p, (void *) native_info_p);
3228  }
3229
3230  return false;
3231} /* jerry_delete_object_native_pointer */
3232
3233/**
3234 * Applies the given function to the every property in the object.
3235 *
3236 * @return true - if object fields traversal was performed successfully, i.e.:
3237 *                - no unhandled exceptions were thrown in object fields traversal;
3238 *                - object fields traversal was stopped on callback that returned false;
3239 *         false - otherwise,
3240 *                 if getter of field threw a exception or unhandled exceptions were thrown during traversal;
3241 */
3242bool
3243jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */
3244                               jerry_object_property_foreach_t foreach_p, /**< foreach function */
3245                               void *user_data_p) /**< user data for foreach function */
3246{
3247  jerry_assert_api_available ();
3248
3249  if (!ecma_is_value_object (obj_val))
3250  {
3251    return false;
3252  }
3253
3254  ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3255  ecma_collection_t *names_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE_PROTOTYPE);
3256
3257#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
3258  if (names_p == NULL)
3259  {
3260    // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
3261    jcontext_release_exception ();
3262    return false;
3263  }
3264#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
3265
3266  ecma_value_t *buffer_p = names_p->buffer_p;
3267
3268  ecma_value_t property_value = ECMA_VALUE_EMPTY;
3269
3270  bool continuous = true;
3271
3272  for (uint32_t i = 0; continuous && (i < names_p->item_count); i++)
3273  {
3274    ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]);
3275
3276    property_value = ecma_op_object_get (object_p, property_name_p);
3277
3278    if (ECMA_IS_VALUE_ERROR (property_value))
3279    {
3280      break;
3281    }
3282
3283    continuous = foreach_p (buffer_p[i], property_value, user_data_p);
3284    ecma_free_value (property_value);
3285  }
3286
3287  ecma_collection_free (names_p);
3288
3289  if (!ECMA_IS_VALUE_ERROR (property_value))
3290  {
3291    return true;
3292  }
3293
3294  jcontext_release_exception ();
3295  return false;
3296} /* jerry_foreach_object_property */
3297
3298/**
3299 * Resolve or reject the promise with an argument.
3300 *
3301 * @return undefined value - if success
3302 *         value marked with error flag - otherwise
3303 */
3304jerry_value_t
3305jerry_resolve_or_reject_promise (jerry_value_t promise, /**< the promise value */
3306                                 jerry_value_t argument, /**< the argument */
3307                                 bool is_resolve) /**< whether the promise should be resolved or rejected */
3308{
3309  jerry_assert_api_available ();
3310
3311#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
3312  if (!ecma_is_value_object (promise) || !ecma_is_promise (ecma_get_object_from_value (promise)))
3313  {
3314    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3315  }
3316
3317  if (ecma_is_value_error_reference (argument))
3318  {
3319    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
3320  }
3321
3322  lit_magic_string_id_t prop_name = (is_resolve ? LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION
3323                                                : LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);
3324
3325  ecma_value_t function = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (promise), prop_name);
3326
3327  ecma_value_t ret = ecma_op_function_call (ecma_get_object_from_value (function),
3328                                            ECMA_VALUE_UNDEFINED,
3329                                            &argument,
3330                                            1);
3331
3332  ecma_free_value (function);
3333
3334  return ret;
3335#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3336  JERRY_UNUSED (promise);
3337  JERRY_UNUSED (argument);
3338  JERRY_UNUSED (is_resolve);
3339
3340  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
3341#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3342} /* jerry_resolve_or_reject_promise */
3343
3344/**
3345 * Get the result of a promise.
3346 *
3347 * @return - Promise result
3348 *         - Type error if the promise support was not enabled or the input was not a promise object
3349 */
3350jerry_value_t
3351jerry_get_promise_result (const jerry_value_t promise) /**< promise object to get the result from */
3352{
3353  jerry_assert_api_available ();
3354
3355#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
3356  if (!jerry_value_is_promise (promise))
3357  {
3358    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3359  }
3360
3361  return ecma_promise_get_result (ecma_get_object_from_value (promise));
3362#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3363  JERRY_UNUSED (promise);
3364  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
3365#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3366} /* jerry_get_promise_result */
3367
3368/**
3369 * Get the state of a promise object.
3370 *
3371 * @return - the state of the promise (one of the jerry_promise_state_t enum values)
3372 *         - JERRY_PROMISE_STATE_NONE is only returned if the input is not a promise object
3373 *           or the promise support was not enabled.
3374 */
3375jerry_promise_state_t
3376jerry_get_promise_state (const jerry_value_t promise) /**< promise object to get the state from */
3377{
3378  jerry_assert_api_available ();
3379
3380#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
3381  if (!jerry_value_is_promise (promise))
3382  {
3383    return JERRY_PROMISE_STATE_NONE;
3384  }
3385
3386  uint16_t flags = ecma_promise_get_flags (ecma_get_object_from_value (promise));
3387  flags &= (ECMA_PROMISE_IS_PENDING | ECMA_PROMISE_IS_FULFILLED);
3388
3389  return (flags ? flags : JERRY_PROMISE_STATE_REJECTED);
3390#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3391  JERRY_UNUSED (promise);
3392  return JERRY_PROMISE_STATE_NONE;
3393#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3394} /* jerry_get_promise_state */
3395
3396/**
3397 * Call the SymbolDescriptiveString ecma builtin operation on the symbol value.
3398 *
3399 * Note:
3400 *      returned value must be freed with jerry_release_value, when it is no longer needed.
3401 *
3402 * @return string value containing the symbol's descriptive string - if success
3403 *         thrown error - otherwise
3404 */
3405jerry_value_t
3406jerry_get_symbol_descriptive_string (const jerry_value_t symbol) /**< symbol value */
3407{
3408  jerry_assert_api_available ();
3409
3410#if ENABLED (JERRY_ES2015)
3411  if (!ecma_is_value_symbol (symbol))
3412  {
3413    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3414  }
3415
3416  /* Note: This operation cannot throw an error */
3417  return ecma_get_symbol_descriptive_string (symbol);
3418#else /* !ENABLED (JERRY_ES2015) */
3419  JERRY_UNUSED (symbol);
3420
3421  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported.")));
3422#endif /* ENABLED (JERRY_ES2015) */
3423} /** jerry_get_symbol_descriptive_string */
3424
3425/**
3426 * Validate UTF-8 string
3427 *
3428 * @return true - if UTF-8 string is well-formed
3429 *         false - otherwise
3430 */
3431bool
3432jerry_is_valid_utf8_string (const jerry_char_t *utf8_buf_p, /**< UTF-8 string */
3433                            jerry_size_t buf_size) /**< string size */
3434{
3435  return lit_is_valid_utf8_string ((lit_utf8_byte_t *) utf8_buf_p,
3436                                   (lit_utf8_size_t) buf_size);
3437} /* jerry_is_valid_utf8_string */
3438
3439/**
3440 * Validate CESU-8 string
3441 *
3442 * @return true - if CESU-8 string is well-formed
3443 *         false - otherwise
3444 */
3445bool
3446jerry_is_valid_cesu8_string (const jerry_char_t *cesu8_buf_p, /**< CESU-8 string */
3447                             jerry_size_t buf_size) /**< string size */
3448{
3449  return lit_is_valid_cesu8_string ((lit_utf8_byte_t *) cesu8_buf_p,
3450                                    (lit_utf8_size_t) buf_size);
3451} /* jerry_is_valid_cesu8_string */
3452
3453/**
3454 * Allocate memory on the engine's heap.
3455 *
3456 * Note:
3457 *      This function may take away memory from the executed JavaScript code.
3458 *      If any other dynamic memory allocation API is available (e.g., libc
3459 *      malloc), it should be used instead.
3460 *
3461 * @return allocated memory on success
3462 *         NULL otherwise
3463 */
3464void *
3465jerry_heap_alloc (size_t size) /**< size of the memory block */
3466{
3467  jerry_assert_api_available ();
3468
3469  return jmem_heap_alloc_block_null_on_error (size);
3470} /* jerry_heap_alloc */
3471
3472/**
3473 * Free memory allocated on the engine's heap.
3474 */
3475void
3476jerry_heap_free (void *mem_p, /**< value returned by jerry_heap_alloc */
3477                 size_t size) /**< same size as passed to jerry_heap_alloc */
3478{
3479  jerry_assert_api_available ();
3480
3481  jmem_heap_free_block (mem_p, size);
3482} /* jerry_heap_free */
3483
3484/**
3485 * Create an external engine context.
3486 *
3487 * @return the pointer to the context.
3488 */
3489jerry_context_t *
3490jerry_create_context (uint32_t heap_size, /**< the size of heap */
3491                      jerry_context_alloc_t alloc, /**< the alloc function */
3492                      void *cb_data_p) /**< the cb_data for alloc function */
3493{
3494  JERRY_UNUSED (heap_size);
3495
3496#if ENABLED (JERRY_EXTERNAL_CONTEXT)
3497
3498  size_t total_size = sizeof (jerry_context_t) + JMEM_ALIGNMENT;
3499
3500#if !ENABLED (JERRY_SYSTEM_ALLOCATOR)
3501  heap_size = JERRY_ALIGNUP (heap_size, JMEM_ALIGNMENT);
3502
3503  /* Minimum heap size is 1Kbyte. */
3504  if (heap_size < 1024)
3505  {
3506    return NULL;
3507  }
3508
3509  total_size += heap_size;
3510#endif /* !ENABLED (JERRY_SYSTEM_ALLOCATOR) */
3511
3512  total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT);
3513
3514  jerry_context_t *context_p = (jerry_context_t *) alloc (total_size, cb_data_p);
3515
3516  if (context_p == NULL)
3517  {
3518    return NULL;
3519  }
3520
3521  memset (context_p, 0, total_size);
3522
3523  uintptr_t context_ptr = ((uintptr_t) context_p) + sizeof (jerry_context_t);
3524  context_ptr = JERRY_ALIGNUP (context_ptr, (uintptr_t) JMEM_ALIGNMENT);
3525
3526  uint8_t *byte_p = (uint8_t *) context_ptr;
3527
3528#if !ENABLED (JERRY_SYSTEM_ALLOCATOR)
3529  context_p->heap_p = (jmem_heap_t *) byte_p;
3530  context_p->heap_size = heap_size;
3531  byte_p += heap_size;
3532#endif /* !ENABLED (JERRY_SYSTEM_ALLOCATOR) */
3533
3534  JERRY_ASSERT (byte_p <= ((uint8_t *) context_p) + total_size);
3535
3536  JERRY_UNUSED (byte_p);
3537  return context_p;
3538
3539#else /* !ENABLED (JERRY_EXTERNAL_CONTEXT) */
3540
3541  JERRY_UNUSED (alloc);
3542  JERRY_UNUSED (cb_data_p);
3543
3544  return NULL;
3545
3546#endif /* ENABLED (JERRY_EXTERNAL_CONTEXT) */
3547} /* jerry_create_context */
3548
3549/**
3550 * If JERRY_VM_EXEC_STOP is enabled the callback passed to this function is
3551 * periodically called with the user_p argument. If frequency is greater
3552 * than 1, the callback is only called at every frequency ticks.
3553 */
3554void
3555jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< periodically called user function */
3556                                 void *user_p, /**< pointer passed to the function */
3557                                 uint32_t frequency) /**< frequency of the function call */
3558{
3559#if ENABLED (JERRY_VM_EXEC_STOP)
3560  if (frequency == 0)
3561  {
3562    frequency = 1;
3563  }
3564
3565  JERRY_CONTEXT (vm_exec_stop_frequency) = frequency;
3566  JERRY_CONTEXT (vm_exec_stop_counter) = frequency;
3567  JERRY_CONTEXT (vm_exec_stop_user_p) = user_p;
3568  JERRY_CONTEXT (vm_exec_stop_cb) = stop_cb;
3569#else /* !ENABLED (JERRY_VM_EXEC_STOP) */
3570  JERRY_UNUSED (stop_cb);
3571  JERRY_UNUSED (user_p);
3572  JERRY_UNUSED (frequency);
3573#endif /* ENABLED (JERRY_VM_EXEC_STOP) */
3574} /* jerry_set_vm_exec_stop_callback */
3575
3576/**
3577 * Get backtrace. The backtrace is an array of strings where
3578 * each string contains the position of the corresponding frame.
3579 * The array length is zero if the backtrace is not available.
3580 *
3581 * @return array value
3582 */
3583jerry_value_t
3584jerry_get_backtrace (uint32_t max_depth) /**< depth limit of the backtrace */
3585{
3586  return vm_get_backtrace (max_depth);
3587} /* jerry_get_backtrace */
3588
3589/**
3590 * Get the resource name (usually a file name) of the currently executed script or the given function object
3591 *
3592 * Note: returned value must be freed with jerry_release_value, when it is no longer needed
3593 *
3594 * @return JS string constructed from
3595 *         - the currently executed function object's resource name, if the given value is undefined
3596 *         - resource name of the function object, if the given value is a function object
3597 *         - "<anonymous>", otherwise
3598 */
3599jerry_value_t
3600jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */
3601{
3602#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
3603  if (ecma_is_value_undefined (value))
3604  {
3605    if (JERRY_CONTEXT (vm_top_context_p) != NULL)
3606    {
3607      return ecma_copy_value (JERRY_CONTEXT (vm_top_context_p)->resource_name);
3608    }
3609  }
3610#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
3611#if ENABLED (JERRY_LINE_INFO)
3612  else if (ecma_is_value_object (value))
3613  {
3614    ecma_object_t *obj_p = ecma_get_object_from_value (value);
3615
3616    if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION
3617        && !ecma_get_object_is_builtin (obj_p))
3618    {
3619      ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p;
3620
3621      const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
3622
3623      return ecma_copy_value (ecma_op_resource_name (bytecode_data_p));
3624    }
3625  }
3626#endif /* ENABLED (JERRY_LINE_INFO) */
3627
3628  JERRY_UNUSED (value);
3629  return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
3630} /* jerry_get_resource_name */
3631
3632/**
3633 * Access the "new.target" value.
3634 *
3635 * The "new.target" value depends on the current call site. That is
3636 * this method will only have a function object result if, at the call site
3637 * it was called inside a constructor method invoked with "new".
3638 *
3639 * @return "undefined" - if at the call site it was not a constructor call.
3640 *         function object - if the current call site is in a constructor call.
3641 */
3642jerry_value_t
3643jerry_get_new_target (void)
3644{
3645#if ENABLED (JERRY_ES2015)
3646  ecma_object_t *current_new_target = JERRY_CONTEXT (current_new_target);
3647
3648  if (current_new_target == NULL)
3649  {
3650    return jerry_create_undefined ();
3651  }
3652
3653  ecma_ref_object (current_new_target);
3654  return ecma_make_object_value (current_new_target);
3655#else /* !ENABLED (JERRY_ES2015) */
3656  return jerry_create_undefined ();
3657#endif /* ENABLED (JERRY_ES2015) */
3658} /* jerry_get_new_target */
3659
3660/**
3661 * Check if the given value is an ArrayBuffer object.
3662 *
3663 * @return true - if it is an ArrayBuffer object
3664 *         false - otherwise
3665 */
3666bool
3667jerry_value_is_arraybuffer (const jerry_value_t value) /**< value to check if it is an ArrayBuffer */
3668{
3669  jerry_assert_api_available ();
3670
3671#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3672  return ecma_is_arraybuffer (value);
3673#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3674  JERRY_UNUSED (value);
3675  return false;
3676#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3677} /* jerry_value_is_arraybuffer */
3678
3679/**
3680 * Creates an ArrayBuffer object with the given length (size).
3681 *
3682 * Notes:
3683 *      * the length is specified in bytes.
3684 *      * returned value must be freed with jerry_release_value, when it is no longer needed.
3685 *      * if the typed arrays are disabled this will return a TypeError.
3686 *
3687 * @return value of the constructed ArrayBuffer object
3688 */
3689jerry_value_t
3690jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffer to create */
3691{
3692  jerry_assert_api_available ();
3693
3694#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3695  return jerry_return (ecma_make_object_value (ecma_arraybuffer_new_object (size)));
3696#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3697  JERRY_UNUSED (size);
3698  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
3699#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3700} /* jerry_create_arraybuffer */
3701
3702/**
3703 * Creates an ArrayBuffer object with user specified buffer.
3704 *
3705 * Notes:
3706 *     * the size is specified in bytes.
3707 *     * the buffer passed should be at least the specified bytes big.
3708 *     * if the typed arrays are disabled this will return a TypeError.
3709 *     * if the size is zero or buffer_p is a null pointer this will return an empty ArrayBuffer.
3710 *
3711 * @return value of the construced ArrayBuffer object
3712 */
3713jerry_value_t
3714jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the buffer to used */
3715                                   uint8_t *buffer_p, /**< buffer to use as the ArrayBuffer's backing */
3716                                   jerry_object_native_free_callback_t free_cb) /**< buffer free callback */
3717{
3718  jerry_assert_api_available ();
3719
3720#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3721  ecma_object_t *arraybuffer;
3722
3723  if (JERRY_UNLIKELY (size == 0 || buffer_p == NULL))
3724  {
3725    arraybuffer = ecma_arraybuffer_new_object_external (0, NULL, (ecma_object_native_free_callback_t) free_cb);
3726  }
3727  else
3728  {
3729    arraybuffer = ecma_arraybuffer_new_object_external (size,
3730                                                        buffer_p,
3731                                                        (ecma_object_native_free_callback_t) free_cb);
3732  }
3733
3734  return jerry_return (ecma_make_object_value (arraybuffer));
3735#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3736  JERRY_UNUSED (size);
3737  JERRY_UNUSED (buffer_p);
3738  JERRY_UNUSED (free_cb);
3739  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
3740#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3741} /* jerry_create_arraybuffer_external */
3742
3743/**
3744 * Copy bytes into the ArrayBuffer from a buffer.
3745 *
3746 * Note:
3747 *     * if the object passed is not an ArrayBuffer will return 0.
3748 *
3749 * @return number of bytes copied into the ArrayBuffer.
3750 */
3751jerry_length_t
3752jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer */
3753                         jerry_length_t offset, /**< start offset of the ArrayBuffer */
3754                         const uint8_t *buf_p, /**< buffer to copy from */
3755                         jerry_length_t buf_size) /**< number of bytes to copy from the buffer */
3756{
3757  jerry_assert_api_available ();
3758
3759#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3760  if (!ecma_is_arraybuffer (value))
3761  {
3762    return 0;
3763  }
3764
3765  ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3766  jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
3767
3768  if (offset >= length)
3769  {
3770    return 0;
3771  }
3772
3773  jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size);
3774
3775  if (copy_count > 0)
3776  {
3777    lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
3778
3779    memcpy ((void *) (mem_buffer_p + offset), (void *) buf_p, copy_count);
3780  }
3781
3782  return copy_count;
3783#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3784  JERRY_UNUSED (value);
3785  JERRY_UNUSED (offset);
3786  JERRY_UNUSED (buf_p);
3787  JERRY_UNUSED (buf_size);
3788  return 0;
3789#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3790} /* jerry_arraybuffer_write */
3791
3792/**
3793 * Copy bytes from a buffer into an ArrayBuffer.
3794 *
3795 * Note:
3796 *     * if the object passed is not an ArrayBuffer will return 0.
3797 *
3798 * @return number of bytes read from the ArrayBuffer.
3799 */
3800jerry_length_t
3801jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer to read from */
3802                        jerry_length_t offset, /**< start offset of the ArrayBuffer */
3803                        uint8_t *buf_p, /**< destination buffer to copy to */
3804                        jerry_length_t buf_size) /**< number of bytes to copy into the buffer */
3805{
3806  jerry_assert_api_available ();
3807
3808#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3809  if (!ecma_is_arraybuffer (value))
3810  {
3811    return 0;
3812  }
3813
3814  ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3815  jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
3816
3817  if (offset >= length)
3818  {
3819    return 0;
3820  }
3821
3822  jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size);
3823
3824  if (copy_count > 0)
3825  {
3826    lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
3827
3828    memcpy ((void *) buf_p, (void *) (mem_buffer_p + offset), copy_count);
3829  }
3830
3831  return copy_count;
3832#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3833  JERRY_UNUSED (value);
3834  JERRY_UNUSED (offset);
3835  JERRY_UNUSED (buf_p);
3836  JERRY_UNUSED (buf_size);
3837  return 0;
3838#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3839} /* jerry_arraybuffer_read */
3840
3841/**
3842 * Get the length (size) of the ArrayBuffer in bytes.
3843 *
3844 * Note:
3845 *     This is the 'byteLength' property of an ArrayBuffer.
3846 *
3847 * @return the length of the ArrayBuffer in bytes.
3848 */
3849jerry_length_t
3850jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer */
3851{
3852  jerry_assert_api_available ();
3853
3854#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3855  if (ecma_is_arraybuffer (value))
3856  {
3857    ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3858    return ecma_arraybuffer_get_length (buffer_p);
3859  }
3860#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3861  JERRY_UNUSED (value);
3862#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3863  return 0;
3864} /* jerry_get_arraybuffer_byte_length */
3865
3866/**
3867 * Get a pointer for the start of the ArrayBuffer.
3868 *
3869 * Note:
3870 *    * This is a high-risk operation as the bounds are not checked
3871 *      when accessing the pointer elements.
3872 *
3873 * @return pointer to the back-buffer of the ArrayBuffer.
3874 *         pointer is NULL if the parameter is not an ArrayBuffer
3875 */
3876uint8_t *
3877jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buffer to use */
3878{
3879  jerry_assert_api_available ();
3880
3881#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3882  if (ecma_is_value_error_reference (array_buffer)
3883      || !ecma_is_arraybuffer (array_buffer))
3884  {
3885    return NULL;
3886  }
3887
3888  ecma_object_t *buffer_p = ecma_get_object_from_value (array_buffer);
3889  lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
3890  return (uint8_t *const) mem_buffer_p;
3891#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3892  JERRY_UNUSED (array_buffer);
3893#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3894
3895  return NULL;
3896} /* jerry_get_arraybuffer_pointer */
3897
3898/**
3899 * Get if the ArrayBuffer is detachable.
3900 *
3901 * @return boolean value - if success
3902 *         value marked with error flag - otherwise
3903 */
3904jerry_value_t
3905jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
3906{
3907  jerry_assert_api_available ();
3908
3909#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3910  if (ecma_is_arraybuffer (value))
3911  {
3912    ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3913    return ecma_arraybuffer_is_detachable (buffer_p) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
3914  }
3915#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3916  JERRY_UNUSED (value);
3917#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3918  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
3919} /* jerry_is_arraybuffer_detachable */
3920
3921/**
3922 * Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
3923 * This operation requires the ArrayBuffer to be external that created by
3924 * `jerry_create_arraybuffer_external`.
3925 *
3926 * @return null value - if success
3927 *         value marked with error flag - otherwise
3928 */
3929jerry_value_t
3930jerry_detach_arraybuffer (const jerry_value_t value) /**< ArrayBuffer */
3931{
3932  jerry_assert_api_available ();
3933
3934#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3935  if (ecma_is_arraybuffer (value))
3936  {
3937    ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3938    bool detached = ecma_arraybuffer_detach (buffer_p);
3939    if (!detached)
3940    {
3941      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects a detachable ArrayBuffer.")));
3942    }
3943    return ECMA_VALUE_NULL;
3944  }
3945#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3946  JERRY_UNUSED (value);
3947#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3948  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
3949} /* jerry_detach_arraybuffer */
3950
3951/**
3952 * DataView related functions
3953 */
3954
3955/**
3956 * Creates a DataView object with the given ArrayBuffer, ByteOffset and ByteLength arguments.
3957 *
3958 * Notes:
3959 *      * returned value must be freed with jerry_release_value, when it is no longer needed.
3960 *      * if the DataView bulitin is disabled this will return a TypeError.
3961 *
3962 * @return value of the constructed DataView object - if success
3963 *         created error - otherwise
3964 */
3965jerry_value_t
3966jerry_create_dataview (const jerry_value_t array_buffer, /**< arraybuffer to create DataView from */
3967                       const jerry_length_t byte_offset, /**< offset in bytes, to the first byte in the buffer */
3968                       const jerry_length_t byte_length) /**< number of elements in the byte array */
3969{
3970  jerry_assert_api_available ();
3971
3972#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
3973  if (ecma_is_value_error_reference (array_buffer))
3974  {
3975    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3976  }
3977
3978  ecma_value_t arguments_p[3] =
3979  {
3980    array_buffer,
3981    ecma_make_uint32_value (byte_offset),
3982    ecma_make_uint32_value (byte_length)
3983  };
3984
3985  return jerry_return (ecma_op_dataview_create (arguments_p, 3));
3986#else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
3987  JERRY_UNUSED (array_buffer);
3988  JERRY_UNUSED (byte_offset);
3989  JERRY_UNUSED (byte_length);
3990  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported.")));
3991#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */
3992} /* jerry_create_dataview */
3993
3994/**
3995 * Check if the given value is a DataView object.
3996 *
3997 * @return true - if it is a DataView object
3998 *         false - otherwise
3999 */
4000bool
4001jerry_value_is_dataview (const jerry_value_t value) /**< value to check if it is a DataView object */
4002{
4003  jerry_assert_api_available ();
4004
4005#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
4006  return ecma_is_dataview (value);
4007#else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
4008  JERRY_UNUSED (value);
4009  return false;
4010#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */
4011} /* jerry_value_is_dataview */
4012
4013/**
4014 * Get the underlying ArrayBuffer from a DataView.
4015 *
4016 * Additionally the byteLength and byteOffset properties are also returned
4017 * which were specified when the DataView was created.
4018 *
4019 * Note:
4020 *     the returned value must be freed with a jerry_release_value call
4021 *
4022 * @return ArrayBuffer of a DataView
4023 *         TypeError if the object is not a DataView.
4024 */
4025jerry_value_t
4026jerry_get_dataview_buffer (const jerry_value_t value, /**< DataView to get the arraybuffer from */
4027                           jerry_length_t *byte_offset, /**< [out] byteOffset property */
4028                           jerry_length_t *byte_length) /**< [out] byteLength property */
4029{
4030  jerry_assert_api_available ();
4031
4032#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
4033  if (ecma_is_value_error_reference (value))
4034  {
4035    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
4036  }
4037
4038  ecma_dataview_object_t *dataview_p = ecma_op_dataview_get_object (value);
4039
4040  if (JERRY_UNLIKELY (dataview_p == NULL))
4041  {
4042    return ecma_create_error_reference_from_context ();
4043  }
4044
4045  if (byte_offset != NULL)
4046  {
4047    *byte_offset = dataview_p->byte_offset;
4048  }
4049
4050  if (byte_length != NULL)
4051  {
4052    *byte_length = dataview_p->header.u.class_prop.u.length;
4053  }
4054
4055  ecma_object_t *arraybuffer_p = dataview_p->buffer_p;
4056  ecma_ref_object (arraybuffer_p);
4057
4058  return ecma_make_object_value (arraybuffer_p);
4059#else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
4060  JERRY_UNUSED (value);
4061  JERRY_UNUSED (byte_offset);
4062  JERRY_UNUSED (byte_length);
4063  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported.")));
4064#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */
4065} /* jerry_get_dataview_buffer */
4066
4067/**
4068 * TypedArray related functions
4069 */
4070
4071/**
4072 * Check if the given value is a TypedArray object.
4073 *
4074 * @return true - if it is a TypedArray object
4075 *         false - otherwise
4076 */
4077bool
4078jerry_value_is_typedarray (jerry_value_t value) /**< value to check if it is a TypedArray */
4079{
4080  jerry_assert_api_available ();
4081
4082#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4083  return ecma_is_typedarray (value);
4084#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4085  JERRY_UNUSED (value);
4086  return false;
4087#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4088} /* jerry_value_is_typedarray */
4089
4090#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4091/**
4092 * TypedArray mapping type
4093 */
4094typedef struct
4095{
4096  jerry_typedarray_type_t api_type; /**< api type */
4097  ecma_builtin_id_t prototype_id; /**< prototype ID */
4098  ecma_typedarray_type_t id; /**< typedArray ID */
4099  uint8_t element_size_shift; /**< element size shift */
4100} jerry_typedarray_mapping_t;
4101
4102/**
4103 * List of TypedArray mappings
4104 */
4105static jerry_typedarray_mapping_t jerry_typedarray_mappings[] =
4106{
4107#define TYPEDARRAY_ENTRY(NAME, LIT_NAME, SIZE_SHIFT) \
4108  { JERRY_TYPEDARRAY_ ## NAME, ECMA_BUILTIN_ID_ ## NAME ## ARRAY_PROTOTYPE, \
4109    ECMA_ ## LIT_NAME ## _ARRAY, SIZE_SHIFT }
4110
4111  TYPEDARRAY_ENTRY (UINT8, UINT8, 0),
4112  TYPEDARRAY_ENTRY (UINT8CLAMPED, UINT8_CLAMPED, 0),
4113  TYPEDARRAY_ENTRY (INT8, INT8, 0),
4114  TYPEDARRAY_ENTRY (UINT16, UINT16, 1),
4115  TYPEDARRAY_ENTRY (INT16, INT16, 1),
4116  TYPEDARRAY_ENTRY (UINT32, UINT32, 2),
4117  TYPEDARRAY_ENTRY (INT32, INT32, 2),
4118  TYPEDARRAY_ENTRY (FLOAT32, FLOAT32, 2),
4119#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
4120  TYPEDARRAY_ENTRY (FLOAT64, FLOAT64, 3),
4121#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
4122
4123#undef TYPEDARRAY_ENTRY
4124};
4125
4126/**
4127 * Helper function to get the TypedArray prototype, typedArray id, and element size shift
4128 * information.
4129 *
4130 * @return true - if the TypedArray information was found
4131 *         false - if there is no such TypedArray type
4132 */
4133static bool
4134jerry_typedarray_find_by_type (jerry_typedarray_type_t type_name, /**< type of the TypedArray */
4135                               ecma_builtin_id_t *prototype_id, /**< [out] found prototype object id */
4136                               ecma_typedarray_type_t *id, /**< [out] found typedArray id */
4137                               uint8_t *element_size_shift) /**< [out] found element size shift value */
4138{
4139  JERRY_ASSERT (prototype_id != NULL);
4140  JERRY_ASSERT (id != NULL);
4141  JERRY_ASSERT (element_size_shift != NULL);
4142
4143  for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
4144  {
4145    if (type_name == jerry_typedarray_mappings[i].api_type)
4146    {
4147      *prototype_id = jerry_typedarray_mappings[i].prototype_id;
4148      *id = jerry_typedarray_mappings[i].id;
4149      *element_size_shift = jerry_typedarray_mappings[i].element_size_shift;
4150      return true;
4151    }
4152  }
4153
4154  return false;
4155} /* jerry_typedarray_find_by_type */
4156
4157#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4158
4159/**
4160 * Create a TypedArray object with a given type and length.
4161 *
4162 * Notes:
4163 *      * returns TypeError if an incorrect type (type_name) is specified.
4164 *      * byteOffset property will be set to 0.
4165 *      * byteLength property will be a multiple of the length parameter (based on the type).
4166 *
4167 * @return - new TypedArray object
4168 */
4169jerry_value_t
4170jerry_create_typedarray (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
4171                         jerry_length_t length) /**< element count of the new TypedArray */
4172{
4173  jerry_assert_api_available ();
4174
4175#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4176  ecma_builtin_id_t prototype_id = 0;
4177  ecma_typedarray_type_t id = 0;
4178  uint8_t element_size_shift = 0;
4179
4180  if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift))
4181  {
4182    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
4183  }
4184
4185  ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
4186
4187  ecma_value_t array_value = ecma_typedarray_create_object_with_length (length,
4188                                                                        NULL,
4189                                                                        prototype_obj_p,
4190                                                                        element_size_shift,
4191                                                                        id);
4192
4193  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value));
4194
4195  return array_value;
4196#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4197  JERRY_UNUSED (type_name);
4198  JERRY_UNUSED (length);
4199  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
4200#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4201} /* jerry_create_typedarray */
4202
4203/**
4204 * Create a TypedArray object using the given arraybuffer and size information.
4205 *
4206 * Notes:
4207 *      * returns TypeError if an incorrect type (type_name) is specified.
4208 *      * this is the 'new %TypedArray%(arraybuffer, byteOffset, length)' equivalent call.
4209 *
4210 * @return - new TypedArray object
4211 */
4212jerry_value_t
4213jerry_create_typedarray_for_arraybuffer_sz (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
4214                                            const jerry_value_t arraybuffer, /**< ArrayBuffer to use */
4215                                            jerry_length_t byte_offset, /**< offset for the ArrayBuffer */
4216                                            jerry_length_t length) /**< number of elements to use from ArrayBuffer */
4217{
4218  jerry_assert_api_available ();
4219
4220#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4221  if (ecma_is_value_error_reference (arraybuffer))
4222  {
4223    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4224  }
4225
4226  ecma_builtin_id_t prototype_id = 0;
4227  ecma_typedarray_type_t id = 0;
4228  uint8_t element_size_shift = 0;
4229
4230  if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift))
4231  {
4232    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
4233  }
4234
4235  if (!ecma_is_arraybuffer (arraybuffer))
4236  {
4237    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an ArrayBuffer")));
4238  }
4239
4240  ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
4241  ecma_value_t arguments_p[3] =
4242  {
4243    arraybuffer,
4244    ecma_make_uint32_value (byte_offset),
4245    ecma_make_uint32_value (length)
4246  };
4247
4248  ecma_value_t array_value = ecma_op_create_typedarray (arguments_p, 3, prototype_obj_p, element_size_shift, id);
4249  ecma_free_value (arguments_p[1]);
4250  ecma_free_value (arguments_p[2]);
4251
4252  return jerry_return (array_value);
4253#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4254  JERRY_UNUSED (type_name);
4255  JERRY_UNUSED (arraybuffer);
4256  JERRY_UNUSED (byte_offset);
4257  JERRY_UNUSED (length);
4258  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
4259#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4260} /* jerry_create_typedarray_for_arraybuffer_sz */
4261
4262/**
4263 * Create a TypedArray object using the given arraybuffer and size information.
4264 *
4265 * Notes:
4266 *      * returns TypeError if an incorrect type (type_name) is specified.
4267 *      * this is the 'new %TypedArray%(arraybuffer)' equivalent call.
4268 *
4269 * @return - new TypedArray object
4270 */
4271jerry_value_t
4272jerry_create_typedarray_for_arraybuffer (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
4273                                         const jerry_value_t arraybuffer) /**< ArrayBuffer to use */
4274{
4275  jerry_assert_api_available ();
4276
4277#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4278  if (ecma_is_value_error_reference (arraybuffer))
4279  {
4280    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4281  }
4282
4283  jerry_length_t byteLength = jerry_get_arraybuffer_byte_length (arraybuffer);
4284  return jerry_create_typedarray_for_arraybuffer_sz (type_name, arraybuffer, 0, byteLength);
4285#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4286  JERRY_UNUSED (type_name);
4287  JERRY_UNUSED (arraybuffer);
4288  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
4289#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4290} /* jerry_create_typedarray_for_arraybuffer */
4291
4292/**
4293 * Get the type of the TypedArray.
4294 *
4295 * @return - type of the TypedArray
4296 *         - JERRY_TYPEDARRAY_INVALID if the argument is not a TypedArray
4297 */
4298jerry_typedarray_type_t
4299jerry_get_typedarray_type (jerry_value_t value) /**< object to get the TypedArray type */
4300{
4301  jerry_assert_api_available ();
4302
4303#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4304  if (!ecma_is_typedarray (value))
4305  {
4306    return JERRY_TYPEDARRAY_INVALID;
4307  }
4308
4309  ecma_object_t *array_p = ecma_get_object_from_value (value);
4310  ecma_typedarray_type_t class_type = ecma_get_typedarray_id (array_p);
4311
4312  for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
4313  {
4314    if (class_type == jerry_typedarray_mappings[i].id)
4315    {
4316      return jerry_typedarray_mappings[i].api_type;
4317    }
4318  }
4319#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4320  JERRY_UNUSED (value);
4321#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4322
4323  return JERRY_TYPEDARRAY_INVALID;
4324} /* jerry_get_typedarray_type */
4325
4326/**
4327 * Get the element count of the TypedArray.
4328 *
4329 * @return length of the TypedArray.
4330 */
4331jerry_length_t
4332jerry_get_typedarray_length (jerry_value_t value) /**< TypedArray to query */
4333{
4334  jerry_assert_api_available ();
4335
4336#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4337  if (ecma_is_typedarray (value))
4338  {
4339    ecma_object_t *array_p = ecma_get_object_from_value (value);
4340    return ecma_typedarray_get_length (array_p);
4341  }
4342#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4343  JERRY_UNUSED (value);
4344#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4345
4346  return 0;
4347} /* jerry_get_typedarray_length */
4348
4349/**
4350 * Get the underlying ArrayBuffer from a TypedArray.
4351 *
4352 * Additionally the byteLength and byteOffset properties are also returned
4353 * which were specified when the TypedArray was created.
4354 *
4355 * Note:
4356 *     the returned value must be freed with a jerry_release_value call
4357 *
4358 * @return ArrayBuffer of a TypedArray
4359 *         TypeError if the object is not a TypedArray.
4360 */
4361jerry_value_t
4362jerry_get_typedarray_buffer (jerry_value_t value, /**< TypedArray to get the arraybuffer from */
4363                             jerry_length_t *byte_offset, /**< [out] byteOffset property */
4364                             jerry_length_t *byte_length) /**< [out] byteLength property */
4365{
4366  jerry_assert_api_available ();
4367
4368#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4369  if (!ecma_is_typedarray (value))
4370  {
4371    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Object is not a TypedArray.")));
4372  }
4373
4374  ecma_object_t *array_p = ecma_get_object_from_value (value);
4375  uint8_t shift = ecma_typedarray_get_element_size_shift (array_p);
4376
4377  if (byte_length != NULL)
4378  {
4379    *byte_length = (jerry_length_t) (ecma_typedarray_get_length (array_p) << shift);
4380  }
4381
4382  if (byte_offset != NULL)
4383  {
4384    *byte_offset = (jerry_length_t) ecma_typedarray_get_offset (array_p);
4385  }
4386
4387  ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_p);
4388  ecma_ref_object (arraybuffer_p);
4389  return jerry_return (ecma_make_object_value (arraybuffer_p));
4390#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4391  JERRY_UNUSED (value);
4392  JERRY_UNUSED (byte_length);
4393  JERRY_UNUSED (byte_offset);
4394  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray is not supported.")));
4395#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4396} /* jerry_get_typedarray_buffer */
4397
4398/**
4399 * Create an object from JSON
4400 *
4401 * Note:
4402 *      The returned value must be freed with jerry_release_value
4403 * @return jerry_value_t from json formated string or an error massage
4404 */
4405jerry_value_t
4406jerry_json_parse (const jerry_char_t *string_p, /**< json string */
4407                  jerry_size_t string_size) /**< json string size */
4408{
4409  jerry_assert_api_available ();
4410
4411#if ENABLED (JERRY_BUILTIN_JSON)
4412  ecma_value_t ret_value = ecma_builtin_json_parse_buffer (string_p, string_size);
4413
4414  if (ecma_is_value_undefined (ret_value))
4415  {
4416    ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON string parse error.")));
4417  }
4418
4419  return ret_value;
4420#else /* !ENABLED (JERRY_BUILTIN_JSON) */
4421  JERRY_UNUSED (string_p);
4422  JERRY_UNUSED (string_size);
4423
4424  return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
4425#endif /* ENABLED (JERRY_BUILTIN_JSON) */
4426} /* jerry_json_parse */
4427
4428/**
4429 * Create a Json formated string from an object
4430 *
4431 * Note:
4432 *      The returned value must be freed with jerry_release_value
4433 * @return json formated jerry_value_t or an error massage
4434 */
4435jerry_value_t
4436jerry_json_stringify (const jerry_value_t object_to_stringify) /**< a jerry_object_t to stringify */
4437{
4438  jerry_assert_api_available ();
4439#if ENABLED (JERRY_BUILTIN_JSON)
4440  ecma_value_t ret_value = ecma_builtin_json_string_from_object (object_to_stringify);
4441
4442  if (ecma_is_value_error_reference (object_to_stringify))
4443  {
4444    return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4445  }
4446
4447  if (ecma_is_value_undefined (ret_value))
4448  {
4449    ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON stringify error.")));
4450  }
4451
4452  return ret_value;
4453#else /* ENABLED (JERRY_BUILTIN_JSON) */
4454  JERRY_UNUSED (object_to_stringify);
4455
4456  return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
4457#endif /* ENABLED (JERRY_BUILTIN_JSON) */
4458} /* jerry_json_stringify */
4459
4460/**
4461 * Create a container type specified in jerry_container_type_t.
4462 * The container can be created with a list of arguments, which will be passed to the container constructor to be
4463 * inserted to the container.
4464 *
4465 * Note:
4466 *      The returned value must be freed with jerry_release_value
4467 * @return jerry_value_t representing a container with the given type.
4468 */
4469jerry_value_t
4470jerry_create_container (jerry_container_type_t container_type, /**< Type of the container */
4471                        const jerry_value_t *arguments_list_p, /**< arguments list */
4472                        jerry_length_t arguments_list_len) /**< Length of arguments list */
4473{
4474  jerry_assert_api_available ();
4475
4476#if ENABLED (JERRY_ES2015_BUILTIN_CONTAINER)
4477  for (jerry_length_t i = 0; i < arguments_list_len; i++)
4478  {
4479    if (ecma_is_value_error_reference (arguments_list_p[i]))
4480    {
4481      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4482    }
4483  }
4484
4485  lit_magic_string_id_t lit_id;
4486  ecma_builtin_id_t proto_id;
4487  ecma_builtin_id_t ctor_id;
4488
4489  switch (container_type)
4490  {
4491#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
4492    case JERRY_CONTAINER_TYPE_MAP:
4493    {
4494      lit_id = LIT_MAGIC_STRING_MAP_UL;
4495      proto_id = ECMA_BUILTIN_ID_MAP_PROTOTYPE;
4496      ctor_id = ECMA_BUILTIN_ID_MAP;
4497      break;
4498    }
4499#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
4500#if ENABLED (JERRY_ES2015_BUILTIN_SET)
4501    case JERRY_CONTAINER_TYPE_SET:
4502    {
4503      lit_id = LIT_MAGIC_STRING_SET_UL;
4504      proto_id = ECMA_BUILTIN_ID_SET_PROTOTYPE;
4505      ctor_id = ECMA_BUILTIN_ID_SET;
4506      break;
4507    }
4508#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
4509#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP)
4510    case JERRY_CONTAINER_TYPE_WEAKMAP:
4511    {
4512      lit_id = LIT_MAGIC_STRING_WEAKMAP_UL;
4513      proto_id = ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE;
4514      ctor_id = ECMA_BUILTIN_ID_WEAKMAP;
4515      break;
4516    }
4517#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
4518#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
4519    case JERRY_CONTAINER_TYPE_WEAKSET:
4520    {
4521      lit_id = LIT_MAGIC_STRING_WEAKSET_UL;
4522      proto_id = ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE;
4523      ctor_id = ECMA_BUILTIN_ID_WEAKSET;
4524      break;
4525    }
4526#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
4527    default:
4528    {
4529      return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Invalid container type.")));
4530    }
4531  }
4532  ecma_object_t * old_new_target_p = JERRY_CONTEXT (current_new_target);
4533
4534  if (old_new_target_p == NULL)
4535  {
4536    JERRY_CONTEXT (current_new_target) = ecma_builtin_get (ctor_id);
4537  }
4538
4539  ecma_value_t container_value = ecma_op_container_create (arguments_list_p,
4540                                                           arguments_list_len,
4541                                                           lit_id,
4542                                                           proto_id);
4543
4544  JERRY_CONTEXT (current_new_target) = old_new_target_p;
4545  return container_value;
4546#else /* !ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4547  JERRY_UNUSED (arguments_list_p);
4548  JERRY_UNUSED (arguments_list_len);
4549  JERRY_UNUSED (container_type);
4550  return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Containers are disabled.")));
4551#endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4552} /* jerry_create_container */
4553
4554/**
4555 * Get the type of the given container object.
4556 *
4557 * @return Corresponding type to the given container object.
4558 */
4559jerry_container_type_t
4560jerry_get_container_type (const jerry_value_t value) /**< the container object */
4561{
4562  jerry_assert_api_available ();
4563
4564#if ENABLED (JERRY_ES2015_BUILTIN_CONTAINER)
4565  if (ecma_is_value_object (value))
4566  {
4567    ecma_object_t *obj_p = ecma_get_object_from_value (value);
4568
4569    if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS)
4570    {
4571      uint16_t type = ((ecma_extended_object_t *) obj_p)->u.class_prop.class_id;
4572
4573      switch (type)
4574      {
4575#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
4576        case LIT_MAGIC_STRING_MAP_UL:
4577        {
4578          return JERRY_CONTAINER_TYPE_MAP;
4579        }
4580#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
4581#if ENABLED (JERRY_ES2015_BUILTIN_SET)
4582        case LIT_MAGIC_STRING_SET_UL:
4583        {
4584          return JERRY_CONTAINER_TYPE_SET;
4585        }
4586#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
4587#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP)
4588        case LIT_MAGIC_STRING_WEAKMAP_UL:
4589        {
4590          return JERRY_CONTAINER_TYPE_WEAKMAP;
4591        }
4592#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
4593#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
4594        case LIT_MAGIC_STRING_WEAKSET_UL:
4595        {
4596          return JERRY_CONTAINER_TYPE_WEAKSET;
4597        }
4598#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
4599        default:
4600        {
4601          return JERRY_CONTAINER_TYPE_INVALID;
4602        }
4603      }
4604    }
4605  }
4606
4607#else /* !ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4608  JERRY_UNUSED (value);
4609#endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4610  return JERRY_CONTAINER_TYPE_INVALID;
4611} /* jerry_get_container_type */
4612
4613#if defined(JERRY_HEAPDUMP)
4614void JerryHeapdumpRun(const char* filepath)
4615{
4616  SetHeapdumpTraring(true);
4617  LogHeapdumpInit(filepath);
4618  LogHeapdump("[\n");
4619  DumpInfoObject(ecma_builtin_get_global(), HEAPDUMP_OBJECT_GLOBAL);
4620  DumpInfoObject(ecma_get_global_environment(), HEAPDUMP_OBJECT_GLOBAL);
4621  ecma_gc_run();
4622  LogHeapdump("{}]\n");
4623  SetHeapdumpTraring(false);
4624  LogHeapdumpClose();
4625}
4626#endif
4627
4628#if defined(JERRY_REF_TRACKER)
4629void JerryRefTrackerStart(const char* filepath)
4630{
4631  SetRefTrackerEnabled(true);
4632  LogTrackerInit(filepath);
4633}
4634#endif
4635
4636#if defined(JERRY_REF_TRACKER)
4637void JerryRefTrackerStop(void)
4638{
4639  SetRefTrackerEnabled(false);
4640  LogTrackerClose();
4641}
4642#endif
4643
4644/**
4645 * @}
4646 */
4647