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
65 JERRY_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
68 JERRY_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
78 JERRY_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)
85 JERRY_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 */
93 JERRY_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
103 JERRY_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 */
118 static 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 */
123 static 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 */
148 static inline void JERRY_ATTR_ALWAYS_INLINE
jerry_assert_api_available(void)149 jerry_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 */
157 static inline void JERRY_ATTR_ALWAYS_INLINE
jerry_make_api_available(void)158 jerry_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 */
166 static inline void JERRY_ATTR_ALWAYS_INLINE
jerry_make_api_unavailable(void)167 jerry_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 */
177 static jerry_value_t
jerry_return(jerry_value_t value)178 jerry_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 */
193 static inline jerry_value_t JERRY_ATTR_ALWAYS_INLINE
jerry_throw(jerry_value_t value)194 jerry_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
jerry_vla_malloc(uint32_t size)201 char* 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
jerry_vla_free(char * p)212 void jerry_vla_free (char* p)
213 {
214 OhosFree (p);
215 }
216 #endif
217
218 /**
219 * Jerry engine initialization
220 */
221 void
jerry_init(jerry_init_flag_t flags)222 jerry_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 */
245 void
jerry_cleanup(void)246 jerry_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 */
302 void *
jerry_get_context_data(const jerry_context_data_manager_t * manager_p)303 jerry_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 */
338 void
jerry_register_magic_strings(const jerry_char_t * const * ex_str_items_p,uint32_t count,const jerry_length_t * str_lengths_p)339 jerry_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 */
354 void
jerry_gc(jerry_gc_mode_t mode)355 jerry_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 */
375 bool
jerry_get_memory_stats(jerry_heap_stats_t * out_stats_p)376 jerry_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 */
409 bool
jerry_run_simple(const jerry_char_t * script_source_p,size_t script_source_size,jerry_init_flag_t flags)410 jerry_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 */
445 jerry_value_t
jerry_parse(const jerry_char_t * resource_name_p,size_t resource_name_length,const jerry_char_t * source_p,size_t source_size,uint32_t parse_opts)446 jerry_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 */
519 jerry_value_t
jerry_parse_function(const jerry_char_t * resource_name_p,size_t resource_name_length,const jerry_char_t * arg_list_p,size_t arg_list_size,const jerry_char_t * source_p,size_t source_size,uint32_t parse_opts)520 jerry_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 */
604 jerry_value_t
jerry_run(const jerry_value_t func_val)605 jerry_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 */
643 jerry_value_t
jerry_eval(const jerry_char_t * source_p,size_t source_size,uint32_t parse_opts)644 jerry_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 */
663 jerry_value_t
jerry_run_all_enqueued_jobs(void)664 jerry_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 */
683 jerry_value_t
jerry_get_global_object(void)684 jerry_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 */
698 bool
jerry_value_is_abort(const jerry_value_t value)699 jerry_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 */
719 bool
jerry_value_is_array(const jerry_value_t value)720 jerry_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 */
734 bool
jerry_value_is_boolean(const jerry_value_t value)735 jerry_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 */
748 bool
jerry_value_is_constructor(const jerry_value_t value)749 jerry_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 */
762 bool
jerry_value_is_error(const jerry_value_t value)763 jerry_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 */
776 bool
jerry_value_is_function(const jerry_value_t value)777 jerry_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 */
790 bool
jerry_value_is_number(const jerry_value_t value)791 jerry_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 */
804 bool
jerry_value_is_null(const jerry_value_t value)805 jerry_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 */
818 bool
jerry_value_is_object(const jerry_value_t value)819 jerry_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 */
832 bool
jerry_value_is_promise(const jerry_value_t value)833 jerry_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 */
851 bool
jerry_value_is_proxy(const jerry_value_t value)852 jerry_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 */
870 bool
jerry_value_is_string(const jerry_value_t value)871 jerry_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 */
884 bool
jerry_value_is_symbol(const jerry_value_t value)885 jerry_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 */
903 bool
jerry_value_is_undefined(const jerry_value_t value)904 jerry_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 */
916 jerry_type_t
jerry_value_get_type(const jerry_value_t value)917 jerry_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 */
976 bool
jerry_is_feature_enabled(const jerry_feature_t feature)977 jerry_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 */
1063 jerry_value_t
jerry_binary_operation(jerry_binary_operation_t op,const jerry_value_t lhs,const jerry_value_t rhs)1064 jerry_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 */
1138 jerry_value_t
jerry_create_abort_from_value(jerry_value_t value,bool release)1139 jerry_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 */
1173 jerry_value_t
jerry_create_error_from_value(jerry_value_t value,bool release)1174 jerry_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 */
1211 jerry_value_t
jerry_get_value_from_error(jerry_value_t value,bool release)1212 jerry_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 */
1237 jerry_error_t
jerry_get_error_type(jerry_value_t value)1238 jerry_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 */
1261 bool
jerry_get_boolean_value(const jerry_value_t value)1262 jerry_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 */
1274 double
jerry_get_number_value(const jerry_value_t value)1275 jerry_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 */
1293 bool
jerry_value_to_boolean(const jerry_value_t value)1294 jerry_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 */
1315 jerry_value_t
jerry_value_to_number(const jerry_value_t value)1316 jerry_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 */
1337 jerry_value_t
jerry_value_to_object(const jerry_value_t value)1338 jerry_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 */
1359 jerry_value_t
jerry_value_to_primitive(const jerry_value_t value)1360 jerry_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 */
1381 jerry_value_t
jerry_value_to_string(const jerry_value_t value)1382 jerry_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 */
1409 jerry_value_t
jerry_acquire_value(jerry_value_t value)1410 jerry_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 */
1426 void
jerry_release_value(jerry_value_t value)1427 jerry_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 */
1448 jerry_value_t
jerry_create_array(uint32_t size)1449 jerry_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 */
1469 jerry_value_t
jerry_create_boolean(bool value)1470 jerry_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 */
1486 jerry_value_t
jerry_create_error(jerry_error_t error_type,const jerry_char_t * message_p)1487 jerry_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 */
1505 jerry_value_t
jerry_create_error_sz(jerry_error_t error_type,const jerry_char_t * message_p,jerry_size_t message_size)1506 jerry_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 */
1539 jerry_value_t
jerry_create_external_function(jerry_external_handler_t handler_p)1540 jerry_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 */
1557 jerry_value_t
jerry_create_number(double value)1558 jerry_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 */
1573 jerry_value_t
jerry_create_number_infinity(bool sign)1574 jerry_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 */
1590 jerry_value_t
jerry_create_number_nan(void)1591 jerry_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 */
1603 jerry_value_t
jerry_create_undefined(void)1604 jerry_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 */
1616 jerry_value_t
jerry_create_null(void)1617 jerry_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 */
1632 jerry_value_t
jerry_create_object(void)1633 jerry_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 */
1649 jerry_value_t
jerry_create_promise(void)1650 jerry_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 */
1679 jerry_value_t
jerry_create_proxy(const jerry_value_t target,const jerry_value_t handler)1680 jerry_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 */
1707 jerry_value_t
jerry_create_string_from_utf8(const jerry_char_t * str_p)1708 jerry_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 */
1721 jerry_value_t
jerry_create_string_sz_from_utf8(const jerry_char_t * str_p,jerry_size_t str_size)1722 jerry_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 */
1741 jerry_value_t
jerry_create_string(const jerry_char_t * str_p)1742 jerry_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 */
1755 jerry_value_t
jerry_create_string_sz(const jerry_char_t * str_p,jerry_size_t str_size)1756 jerry_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 */
1776 jerry_value_t
jerry_create_symbol(const jerry_value_t value)1777 jerry_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 */
1798 jerry_value_t
jerry_create_regexp(const jerry_char_t * pattern_p,uint16_t flags)1799 jerry_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 */
1810 jerry_value_t
jerry_create_regexp_sz(const jerry_char_t * pattern_p,jerry_size_t pattern_size,uint16_t flags)1811 jerry_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 */
1856 uint32_t
jerry_get_array_length(const jerry_value_t value)1857 jerry_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 */
1884 jerry_size_t
jerry_get_string_size(const jerry_value_t value)1885 jerry_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 */
1905 jerry_size_t
jerry_get_utf8_string_size(const jerry_value_t value)1906 jerry_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 */
1926 jerry_length_t
jerry_get_string_length(const jerry_value_t value)1927 jerry_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 */
1947 jerry_length_t
jerry_get_utf8_string_length(const jerry_value_t value)1948 jerry_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 */
1975 jerry_size_t
jerry_string_to_char_buffer(const jerry_value_t value,jerry_char_t * buffer_p,jerry_size_t buffer_size)1976 jerry_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 */
2014 jerry_size_t
jerry_string_to_utf8_char_buffer(const jerry_value_t value,jerry_char_t * buffer_p,jerry_size_t buffer_size)2015 jerry_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 */
2049 jerry_size_t
jerry_substring_to_char_buffer(const jerry_value_t value,jerry_length_t start_pos,jerry_length_t end_pos,jerry_char_t * buffer_p,jerry_size_t buffer_size)2050 jerry_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 */
2083 jerry_size_t
jerry_substring_to_utf8_char_buffer(const jerry_value_t value,jerry_length_t start_pos,jerry_length_t end_pos,jerry_char_t * buffer_p,jerry_size_t buffer_size)2084 jerry_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 */
2112 jerry_value_t
jerry_has_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val)2113 jerry_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 */
2134 jerry_value_t
jerry_has_own_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val)2135 jerry_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 */
2174 bool
jerry_has_internal_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val)2175 jerry_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 */
2214 bool
jerry_delete_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val)2215 jerry_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 */
2247 bool
jerry_delete_property_by_index(const jerry_value_t obj_val,uint32_t index)2248 jerry_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 */
2281 bool
jerry_delete_internal_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val)2282 jerry_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 */
2331 jerry_value_t
jerry_get_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val)2332 jerry_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 */
2357 jerry_value_t
jerry_get_property_by_index(const jerry_value_t obj_val,uint32_t index)2358 jerry_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 */
2383 jerry_value_t
jerry_get_internal_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val)2384 jerry_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 */
2431 jerry_value_t
jerry_set_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val,const jerry_value_t value_to_set)2432 jerry_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 */
2460 jerry_value_t
jerry_set_property_by_index(const jerry_value_t obj_val,uint32_t index,const jerry_value_t value_to_set)2461 jerry_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 */
2491 bool
jerry_set_internal_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val,const jerry_value_t value_to_set)2492 jerry_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 */
2565 void
jerry_init_property_descriptor_fields(jerry_property_descriptor_t * prop_desc_p)2566 jerry_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 */
2591 jerry_value_t
jerry_define_own_property(const jerry_value_t obj_val,const jerry_value_t prop_name_val,const jerry_property_descriptor_t * prop_desc_p)2592 jerry_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 */
2699 bool
jerry_get_own_property_descriptor(const jerry_value_t obj_val,const jerry_value_t prop_name_val,jerry_property_descriptor_t * prop_desc_p)2700 jerry_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 */
2782 void
jerry_free_property_descriptor_fields(const jerry_property_descriptor_t * prop_desc_p)2783 jerry_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 */
2811 static jerry_value_t
jerry_invoke_function(bool is_invoke_as_constructor,const jerry_value_t func_obj_val,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_size_t args_count)2812 jerry_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 */
2865 jerry_value_t
jerry_call_function(const jerry_value_t func_obj_val,const jerry_value_t this_val,const jerry_value_t args_p[],jerry_size_t args_count)2866 jerry_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 */
2914 jerry_value_t
jerry_construct_object(const jerry_value_t func_obj_val,const jerry_value_t args_p[],jerry_size_t args_count)2915 jerry_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 */
2948 jerry_value_t
jerry_get_object_keys(const jerry_value_t obj_val)2949 jerry_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 */
2971 jerry_value_t
jerry_get_prototype(const jerry_value_t obj_val)2972 jerry_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 */
3007 jerry_value_t
jerry_set_prototype(const jerry_value_t obj_val,const jerry_value_t proto_obj_val)3008 jerry_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 */
3040 static
jerry_object_is_valid_foreach(ecma_object_t * object_p)3041 bool 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 */
3069 bool
jerry_objects_foreach(jerry_objects_foreach_t foreach_p,void * user_data_p)3070 jerry_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 */
3101 bool
jerry_objects_foreach_by_native_info(const jerry_object_native_info_t * native_info_p,jerry_objects_foreach_by_native_info_t foreach_p,void * user_data_p)3102 jerry_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 */
3146 bool
jerry_get_object_native_pointer(const jerry_value_t obj_val,void ** out_native_pointer_p,const jerry_object_native_info_t * native_info_p)3147 jerry_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 */
3189 void
jerry_set_object_native_pointer(const jerry_value_t obj_val,void * native_pointer_p,const jerry_object_native_info_t * native_info_p)3190 jerry_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 */
3217 bool
jerry_delete_object_native_pointer(const jerry_value_t obj_val,const jerry_object_native_info_t * native_info_p)3218 jerry_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 */
3242 bool
jerry_foreach_object_property(const jerry_value_t obj_val,jerry_object_property_foreach_t foreach_p,void * user_data_p)3243 jerry_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 */
3304 jerry_value_t
jerry_resolve_or_reject_promise(jerry_value_t promise,jerry_value_t argument,bool is_resolve)3305 jerry_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 */
3350 jerry_value_t
jerry_get_promise_result(const jerry_value_t promise)3351 jerry_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 */
3375 jerry_promise_state_t
jerry_get_promise_state(const jerry_value_t promise)3376 jerry_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 */
3405 jerry_value_t
jerry_get_symbol_descriptive_string(const jerry_value_t symbol)3406 jerry_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 */
3431 bool
jerry_is_valid_utf8_string(const jerry_char_t * utf8_buf_p,jerry_size_t buf_size)3432 jerry_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 */
3445 bool
jerry_is_valid_cesu8_string(const jerry_char_t * cesu8_buf_p,jerry_size_t buf_size)3446 jerry_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 */
3464 void *
jerry_heap_alloc(size_t size)3465 jerry_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 */
3475 void
jerry_heap_free(void * mem_p,size_t size)3476 jerry_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 */
3489 jerry_context_t *
jerry_create_context(uint32_t heap_size,jerry_context_alloc_t alloc,void * cb_data_p)3490 jerry_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 */
3554 void
jerry_set_vm_exec_stop_callback(jerry_vm_exec_stop_callback_t stop_cb,void * user_p,uint32_t frequency)3555 jerry_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 */
3583 jerry_value_t
jerry_get_backtrace(uint32_t max_depth)3584 jerry_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 */
3599 jerry_value_t
jerry_get_resource_name(const jerry_value_t value)3600 jerry_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 */
3642 jerry_value_t
jerry_get_new_target(void)3643 jerry_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 */
3666 bool
jerry_value_is_arraybuffer(const jerry_value_t value)3667 jerry_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 */
3689 jerry_value_t
jerry_create_arraybuffer(const jerry_length_t size)3690 jerry_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 */
3713 jerry_value_t
jerry_create_arraybuffer_external(const jerry_length_t size,uint8_t * buffer_p,jerry_object_native_free_callback_t free_cb)3714 jerry_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 */
3751 jerry_length_t
jerry_arraybuffer_write(const jerry_value_t value,jerry_length_t offset,const uint8_t * buf_p,jerry_length_t buf_size)3752 jerry_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 */
3800 jerry_length_t
jerry_arraybuffer_read(const jerry_value_t value,jerry_length_t offset,uint8_t * buf_p,jerry_length_t buf_size)3801 jerry_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 */
3849 jerry_length_t
jerry_get_arraybuffer_byte_length(const jerry_value_t value)3850 jerry_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 */
3876 uint8_t *
jerry_get_arraybuffer_pointer(const jerry_value_t array_buffer)3877 jerry_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 */
3904 jerry_value_t
jerry_is_arraybuffer_detachable(const jerry_value_t value)3905 jerry_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 */
3929 jerry_value_t
jerry_detach_arraybuffer(const jerry_value_t value)3930 jerry_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 */
3965 jerry_value_t
jerry_create_dataview(const jerry_value_t array_buffer,const jerry_length_t byte_offset,const jerry_length_t byte_length)3966 jerry_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 */
4000 bool
jerry_value_is_dataview(const jerry_value_t value)4001 jerry_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 */
4025 jerry_value_t
jerry_get_dataview_buffer(const jerry_value_t value,jerry_length_t * byte_offset,jerry_length_t * byte_length)4026 jerry_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 */
4077 bool
jerry_value_is_typedarray(jerry_value_t value)4078 jerry_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 */
4094 typedef 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 */
4105 static 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 */
4133 static bool
jerry_typedarray_find_by_type(jerry_typedarray_type_t type_name,ecma_builtin_id_t * prototype_id,ecma_typedarray_type_t * id,uint8_t * element_size_shift)4134 jerry_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 */
4169 jerry_value_t
jerry_create_typedarray(jerry_typedarray_type_t type_name,jerry_length_t length)4170 jerry_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 */
4212 jerry_value_t
jerry_create_typedarray_for_arraybuffer_sz(jerry_typedarray_type_t type_name,const jerry_value_t arraybuffer,jerry_length_t byte_offset,jerry_length_t length)4213 jerry_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 */
4271 jerry_value_t
jerry_create_typedarray_for_arraybuffer(jerry_typedarray_type_t type_name,const jerry_value_t arraybuffer)4272 jerry_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 */
4298 jerry_typedarray_type_t
jerry_get_typedarray_type(jerry_value_t value)4299 jerry_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 */
4331 jerry_length_t
jerry_get_typedarray_length(jerry_value_t value)4332 jerry_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 */
4361 jerry_value_t
jerry_get_typedarray_buffer(jerry_value_t value,jerry_length_t * byte_offset,jerry_length_t * byte_length)4362 jerry_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 */
4405 jerry_value_t
jerry_json_parse(const jerry_char_t * string_p,jerry_size_t string_size)4406 jerry_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 */
4435 jerry_value_t
jerry_json_stringify(const jerry_value_t object_to_stringify)4436 jerry_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 */
4469 jerry_value_t
jerry_create_container(jerry_container_type_t container_type,const jerry_value_t * arguments_list_p,jerry_length_t arguments_list_len)4470 jerry_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 */
4559 jerry_container_type_t
jerry_get_container_type(const jerry_value_t value)4560 jerry_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)
JerryHeapdumpRun(const char * filepath)4614 void 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)
JerryRefTrackerStart(const char * filepath)4629 void JerryRefTrackerStart(const char* filepath)
4630 {
4631 SetRefTrackerEnabled(true);
4632 LogTrackerInit(filepath);
4633 }
4634 #endif
4635
4636 #if defined(JERRY_REF_TRACKER)
JerryRefTrackerStop(void)4637 void JerryRefTrackerStop(void)
4638 {
4639 SetRefTrackerEnabled(false);
4640 LogTrackerClose();
4641 }
4642 #endif
4643
4644 /**
4645 * @}
4646 */
4647