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 if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) {
2875 if (jerry_debugger_receive (NULL)) {
2876 JERRY_DEBUG_MSG ("resume");
2877 }
2878 }
2879 #endif
2880
2881 if (jerry_value_is_function (func_obj_val) && !ecma_is_value_error_reference (this_val))
2882 {
2883 for (jerry_size_t i = 0; i < args_count; i++)
2884 {
2885 if (ecma_is_value_error_reference (args_p[i]))
2886 {
2887 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
2888 }
2889 }
2890
2891 return jerry_invoke_function (false, func_obj_val, this_val, args_p, args_count);
2892 }
2893
2894 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2895 } /* jerry_call_function */
2896
2897 /**
2898 * Construct object value invoking specified function value as a constructor
2899 *
2900 * Note:
2901 * returned value must be freed with jerry_release_value, when it is no longer needed.
2902 * error flag must not be set for any arguments of this function.
2903 *
2904 * @return returned jerry value of the invoked constructor
2905 */
2906 jerry_value_t
jerry_construct_object(const jerry_value_t func_obj_val,const jerry_value_t args_p[],jerry_size_t args_count)2907 jerry_construct_object (const jerry_value_t func_obj_val, /**< function object to call */
2908 const jerry_value_t args_p[], /**< function's call arguments
2909 * (NULL if arguments number is zero) */
2910 jerry_size_t args_count) /**< number of the arguments */
2911 {
2912 jerry_assert_api_available ();
2913
2914 if (jerry_value_is_constructor (func_obj_val))
2915 {
2916 for (jerry_size_t i = 0; i < args_count; i++)
2917 {
2918 if (ecma_is_value_error_reference (args_p[i]))
2919 {
2920 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
2921 }
2922 }
2923
2924 ecma_value_t this_val = ECMA_VALUE_UNDEFINED;
2925 return jerry_invoke_function (true, func_obj_val, this_val, args_p, args_count);
2926 }
2927
2928 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2929 } /* jerry_construct_object */
2930
2931 /**
2932 * Get keys of the specified object value
2933 *
2934 * Note:
2935 * returned value must be freed with jerry_release_value, when it is no longer needed.
2936 *
2937 * @return array object value - if success
2938 * value marked with error flag - otherwise
2939 */
2940 jerry_value_t
jerry_get_object_keys(const jerry_value_t obj_val)2941 jerry_get_object_keys (const jerry_value_t obj_val) /**< object value */
2942 {
2943 jerry_assert_api_available ();
2944
2945 if (!ecma_is_value_object (obj_val))
2946 {
2947 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2948 }
2949
2950 return ecma_builtin_helper_object_get_properties (ecma_get_object_from_value (obj_val),
2951 ECMA_LIST_ENUMERABLE);
2952 } /* jerry_get_object_keys */
2953
2954 /**
2955 * Get the prototype of the specified object
2956 *
2957 * Note:
2958 * returned value must be freed with jerry_release_value, when it is no longer needed.
2959 *
2960 * @return prototype object or null value - if success
2961 * value marked with error flag - otherwise
2962 */
2963 jerry_value_t
jerry_get_prototype(const jerry_value_t obj_val)2964 jerry_get_prototype (const jerry_value_t obj_val) /**< object value */
2965 {
2966 jerry_assert_api_available ();
2967
2968 if (!ecma_is_value_object (obj_val))
2969 {
2970 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
2971 }
2972
2973 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
2974
2975 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
2976 if (ECMA_OBJECT_IS_PROXY (obj_p))
2977 {
2978 return jerry_return (ecma_proxy_object_get_prototype_of (obj_p));
2979 }
2980 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
2981
2982 if (obj_p->u2.prototype_cp == JMEM_CP_NULL)
2983 {
2984 return ECMA_VALUE_NULL;
2985 }
2986
2987 ecma_object_t *proto_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_p->u2.prototype_cp);
2988 ecma_ref_object (proto_obj_p);
2989
2990 return ecma_make_object_value (proto_obj_p);
2991 } /* jerry_get_prototype */
2992
2993 /**
2994 * Set the prototype of the specified object
2995 *
2996 * @return true value - if success
2997 * value marked with error flag - otherwise
2998 */
2999 jerry_value_t
jerry_set_prototype(const jerry_value_t obj_val,const jerry_value_t proto_obj_val)3000 jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
3001 const jerry_value_t proto_obj_val) /**< prototype object value */
3002 {
3003 jerry_assert_api_available ();
3004
3005 if (!ecma_is_value_object (obj_val)
3006 || ecma_is_value_error_reference (proto_obj_val)
3007 || (!ecma_is_value_object (proto_obj_val) && !ecma_is_value_null (proto_obj_val)))
3008 {
3009 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3010 }
3011 ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
3012
3013 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
3014 if (ECMA_OBJECT_IS_PROXY (obj_p))
3015 {
3016 return jerry_return (ecma_proxy_object_set_prototype_of (obj_p, proto_obj_val));
3017 }
3018 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
3019
3020 return ecma_op_ordinary_object_set_prototype_of (obj_p, proto_obj_val);
3021 } /* jerry_set_prototype */
3022
3023 /**
3024 * Utility to check if a given object can be used for the foreach api calls.
3025 *
3026 * Some objects/classes uses extra internal objects to correctly store data.
3027 * These extre object should never be exposed externally to the API user.
3028 *
3029 * @returns true - if the user can access the object in the callback.
3030 * false - if the object is an internal object which should no be accessed by the user.
3031 */
3032 static
jerry_object_is_valid_foreach(ecma_object_t * object_p)3033 bool jerry_object_is_valid_foreach (ecma_object_t *object_p) /**< object to test */
3034 {
3035 if (ecma_is_lexical_environment (object_p))
3036 {
3037 return false;
3038 }
3039
3040 ecma_object_type_t object_type = ecma_get_object_type (object_p);
3041
3042 if (object_type == ECMA_OBJECT_TYPE_CLASS)
3043 {
3044 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
3045 switch (ext_object_p->u.class_prop.class_id)
3046 {
3047 /* An object's internal property object should not be iterable by foreach. */
3048 case LIT_INTERNAL_MAGIC_STRING_INTERNAL_OBJECT: return false;
3049 }
3050 }
3051
3052 return true;
3053 } /* jerry_object_is_valid_foreach */
3054
3055 /**
3056 * Traverse objects.
3057 *
3058 * @return true - traversal was interrupted by the callback.
3059 * false - otherwise - traversal visited all objects.
3060 */
3061 bool
jerry_objects_foreach(jerry_objects_foreach_t foreach_p,void * user_data_p)3062 jerry_objects_foreach (jerry_objects_foreach_t foreach_p, /**< function pointer of the iterator function */
3063 void *user_data_p) /**< pointer to user data */
3064 {
3065 jerry_assert_api_available ();
3066
3067 JERRY_ASSERT (foreach_p != NULL);
3068
3069 jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp);
3070
3071 while (iter_cp != JMEM_CP_NULL)
3072 {
3073 ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp);
3074
3075 if (jerry_object_is_valid_foreach (iter_p)
3076 && !foreach_p (ecma_make_object_value (iter_p), user_data_p))
3077 {
3078 return true;
3079 }
3080
3081 iter_cp = iter_p->gc_next_cp;
3082 }
3083
3084 return false;
3085 } /* jerry_objects_foreach */
3086
3087 /**
3088 * Traverse objects having a given native type info.
3089 *
3090 * @return true - traversal was interrupted by the callback.
3091 * false - otherwise - traversal visited all objects.
3092 */
3093 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)3094 jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_info_p, /**< the type info
3095 * of the native pointer */
3096 jerry_objects_foreach_by_native_info_t foreach_p, /**< function to apply for
3097 * each matching object */
3098 void *user_data_p) /**< pointer to user data */
3099 {
3100 jerry_assert_api_available ();
3101
3102 JERRY_ASSERT (native_info_p != NULL);
3103 JERRY_ASSERT (foreach_p != NULL);
3104
3105 ecma_native_pointer_t *native_pointer_p;
3106
3107 jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp);
3108
3109 while (iter_cp != JMEM_CP_NULL)
3110 {
3111 ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp);
3112
3113 if (jerry_object_is_valid_foreach (iter_p))
3114 {
3115 native_pointer_p = ecma_get_native_pointer_value (iter_p, (void *) native_info_p);
3116 if (native_pointer_p
3117 && !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->data_p, user_data_p))
3118 {
3119 return true;
3120 }
3121 }
3122
3123 iter_cp = iter_p->gc_next_cp;
3124 }
3125
3126 return false;
3127 } /* jerry_objects_foreach_by_native_info */
3128
3129 /**
3130 * Get native pointer and its type information, associated with the given native type info.
3131 *
3132 * Note:
3133 * If native pointer is present, its type information is returned in out_native_pointer_p
3134 *
3135 * @return true - if there is an associated pointer,
3136 * false - otherwise
3137 */
3138 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)3139 jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get native pointer from */
3140 void **out_native_pointer_p, /**< [out] native pointer */
3141 const jerry_object_native_info_t *native_info_p) /**< the type info
3142 * of the native pointer */
3143 {
3144 jerry_assert_api_available ();
3145
3146 if (!ecma_is_value_object (obj_val))
3147 {
3148 return false;
3149 }
3150
3151 ecma_native_pointer_t *native_pointer_p;
3152 native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val), (void *) native_info_p);
3153
3154 if (native_pointer_p == NULL)
3155 {
3156 return false;
3157 }
3158
3159 if (out_native_pointer_p != NULL)
3160 {
3161 *out_native_pointer_p = native_pointer_p->data_p;
3162 }
3163
3164 return true;
3165 } /* jerry_get_object_native_pointer */
3166
3167 /**
3168 * Set native pointer and an optional type info for the specified object.
3169 *
3170 *
3171 * Note:
3172 * If native pointer was already set for the object, its value is updated.
3173 *
3174 * Note:
3175 * If a non-NULL free callback is specified in the native type info,
3176 * it will be called by the garbage collector when the object is freed.
3177 * Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
3178 * The type info always overwrites the previous value, so passing
3179 * a NULL value deletes the current type info.
3180 */
3181 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)3182 jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set native pointer in */
3183 void *native_pointer_p, /**< native pointer */
3184 const jerry_object_native_info_t *native_info_p) /**< object's native type info */
3185 {
3186 jerry_assert_api_available ();
3187
3188 if (ecma_is_value_object (obj_val))
3189 {
3190 ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3191
3192 ecma_create_native_pointer_property (object_p, native_pointer_p, (void *) native_info_p);
3193 }
3194 } /* jerry_set_object_native_pointer */
3195
3196 /**
3197 * Delete the previously set native pointer by the native type info from the specified object.
3198 *
3199 * Note:
3200 * If the specified object has no matching native pointer for the given native type info
3201 * the function has no effect.
3202 *
3203 * Note:
3204 * This operation cannot throw an exception.
3205 *
3206 * @return true - if the native pointer has been deleted succesfully
3207 * false - otherwise
3208 */
3209 bool
jerry_delete_object_native_pointer(const jerry_value_t obj_val,const jerry_object_native_info_t * native_info_p)3210 jerry_delete_object_native_pointer (const jerry_value_t obj_val, /**< object to delete native pointer from */
3211 const jerry_object_native_info_t *native_info_p) /**< object's native type info */
3212 {
3213 jerry_assert_api_available ();
3214
3215 if (ecma_is_value_object (obj_val))
3216 {
3217 ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3218
3219 return ecma_delete_native_pointer_property (object_p, (void *) native_info_p);
3220 }
3221
3222 return false;
3223 } /* jerry_delete_object_native_pointer */
3224
3225 /**
3226 * Applies the given function to the every property in the object.
3227 *
3228 * @return true - if object fields traversal was performed successfully, i.e.:
3229 * - no unhandled exceptions were thrown in object fields traversal;
3230 * - object fields traversal was stopped on callback that returned false;
3231 * false - otherwise,
3232 * if getter of field threw a exception or unhandled exceptions were thrown during traversal;
3233 */
3234 bool
jerry_foreach_object_property(const jerry_value_t obj_val,jerry_object_property_foreach_t foreach_p,void * user_data_p)3235 jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */
3236 jerry_object_property_foreach_t foreach_p, /**< foreach function */
3237 void *user_data_p) /**< user data for foreach function */
3238 {
3239 jerry_assert_api_available ();
3240
3241 if (!ecma_is_value_object (obj_val))
3242 {
3243 return false;
3244 }
3245
3246 ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
3247 ecma_collection_t *names_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE_PROTOTYPE);
3248
3249 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
3250 if (names_p == NULL)
3251 {
3252 // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release
3253 jcontext_release_exception ();
3254 return false;
3255 }
3256 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
3257
3258 ecma_value_t *buffer_p = names_p->buffer_p;
3259
3260 ecma_value_t property_value = ECMA_VALUE_EMPTY;
3261
3262 bool continuous = true;
3263
3264 for (uint32_t i = 0; continuous && (i < names_p->item_count); i++)
3265 {
3266 ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]);
3267
3268 property_value = ecma_op_object_get (object_p, property_name_p);
3269
3270 if (ECMA_IS_VALUE_ERROR (property_value))
3271 {
3272 break;
3273 }
3274
3275 continuous = foreach_p (buffer_p[i], property_value, user_data_p);
3276 ecma_free_value (property_value);
3277 }
3278
3279 ecma_collection_free (names_p);
3280
3281 if (!ECMA_IS_VALUE_ERROR (property_value))
3282 {
3283 return true;
3284 }
3285
3286 jcontext_release_exception ();
3287 return false;
3288 } /* jerry_foreach_object_property */
3289
3290 /**
3291 * Resolve or reject the promise with an argument.
3292 *
3293 * @return undefined value - if success
3294 * value marked with error flag - otherwise
3295 */
3296 jerry_value_t
jerry_resolve_or_reject_promise(jerry_value_t promise,jerry_value_t argument,bool is_resolve)3297 jerry_resolve_or_reject_promise (jerry_value_t promise, /**< the promise value */
3298 jerry_value_t argument, /**< the argument */
3299 bool is_resolve) /**< whether the promise should be resolved or rejected */
3300 {
3301 jerry_assert_api_available ();
3302
3303 #if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
3304 if (!ecma_is_value_object (promise) || !ecma_is_promise (ecma_get_object_from_value (promise)))
3305 {
3306 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3307 }
3308
3309 if (ecma_is_value_error_reference (argument))
3310 {
3311 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
3312 }
3313
3314 lit_magic_string_id_t prop_name = (is_resolve ? LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION
3315 : LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);
3316
3317 ecma_value_t function = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (promise), prop_name);
3318
3319 ecma_value_t ret = ecma_op_function_call (ecma_get_object_from_value (function),
3320 ECMA_VALUE_UNDEFINED,
3321 &argument,
3322 1);
3323
3324 ecma_free_value (function);
3325
3326 return ret;
3327 #else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3328 JERRY_UNUSED (promise);
3329 JERRY_UNUSED (argument);
3330 JERRY_UNUSED (is_resolve);
3331
3332 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
3333 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3334 } /* jerry_resolve_or_reject_promise */
3335
3336 /**
3337 * Get the result of a promise.
3338 *
3339 * @return - Promise result
3340 * - Type error if the promise support was not enabled or the input was not a promise object
3341 */
3342 jerry_value_t
jerry_get_promise_result(const jerry_value_t promise)3343 jerry_get_promise_result (const jerry_value_t promise) /**< promise object to get the result from */
3344 {
3345 jerry_assert_api_available ();
3346
3347 #if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
3348 if (!jerry_value_is_promise (promise))
3349 {
3350 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3351 }
3352
3353 return ecma_promise_get_result (ecma_get_object_from_value (promise));
3354 #else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3355 JERRY_UNUSED (promise);
3356 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Promise not supported.")));
3357 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3358 } /* jerry_get_promise_result */
3359
3360 /**
3361 * Get the state of a promise object.
3362 *
3363 * @return - the state of the promise (one of the jerry_promise_state_t enum values)
3364 * - JERRY_PROMISE_STATE_NONE is only returned if the input is not a promise object
3365 * or the promise support was not enabled.
3366 */
3367 jerry_promise_state_t
jerry_get_promise_state(const jerry_value_t promise)3368 jerry_get_promise_state (const jerry_value_t promise) /**< promise object to get the state from */
3369 {
3370 jerry_assert_api_available ();
3371
3372 #if ENABLED (JERRY_ES2015_BUILTIN_PROMISE)
3373 if (!jerry_value_is_promise (promise))
3374 {
3375 return JERRY_PROMISE_STATE_NONE;
3376 }
3377
3378 uint16_t flags = ecma_promise_get_flags (ecma_get_object_from_value (promise));
3379 flags &= (ECMA_PROMISE_IS_PENDING | ECMA_PROMISE_IS_FULFILLED);
3380
3381 return (flags ? flags : JERRY_PROMISE_STATE_REJECTED);
3382 #else /* !ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3383 JERRY_UNUSED (promise);
3384 return JERRY_PROMISE_STATE_NONE;
3385 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
3386 } /* jerry_get_promise_state */
3387
3388 /**
3389 * Call the SymbolDescriptiveString ecma builtin operation on the symbol value.
3390 *
3391 * Note:
3392 * returned value must be freed with jerry_release_value, when it is no longer needed.
3393 *
3394 * @return string value containing the symbol's descriptive string - if success
3395 * thrown error - otherwise
3396 */
3397 jerry_value_t
jerry_get_symbol_descriptive_string(const jerry_value_t symbol)3398 jerry_get_symbol_descriptive_string (const jerry_value_t symbol) /**< symbol value */
3399 {
3400 jerry_assert_api_available ();
3401
3402 #if ENABLED (JERRY_ES2015)
3403 if (!ecma_is_value_symbol (symbol))
3404 {
3405 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3406 }
3407
3408 /* Note: This operation cannot throw an error */
3409 return ecma_get_symbol_descriptive_string (symbol);
3410 #else /* !ENABLED (JERRY_ES2015) */
3411 JERRY_UNUSED (symbol);
3412
3413 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported.")));
3414 #endif /* ENABLED (JERRY_ES2015) */
3415 } /** jerry_get_symbol_descriptive_string */
3416
3417 /**
3418 * Validate UTF-8 string
3419 *
3420 * @return true - if UTF-8 string is well-formed
3421 * false - otherwise
3422 */
3423 bool
jerry_is_valid_utf8_string(const jerry_char_t * utf8_buf_p,jerry_size_t buf_size)3424 jerry_is_valid_utf8_string (const jerry_char_t *utf8_buf_p, /**< UTF-8 string */
3425 jerry_size_t buf_size) /**< string size */
3426 {
3427 return lit_is_valid_utf8_string ((lit_utf8_byte_t *) utf8_buf_p,
3428 (lit_utf8_size_t) buf_size);
3429 } /* jerry_is_valid_utf8_string */
3430
3431 /**
3432 * Validate CESU-8 string
3433 *
3434 * @return true - if CESU-8 string is well-formed
3435 * false - otherwise
3436 */
3437 bool
jerry_is_valid_cesu8_string(const jerry_char_t * cesu8_buf_p,jerry_size_t buf_size)3438 jerry_is_valid_cesu8_string (const jerry_char_t *cesu8_buf_p, /**< CESU-8 string */
3439 jerry_size_t buf_size) /**< string size */
3440 {
3441 return lit_is_valid_cesu8_string ((lit_utf8_byte_t *) cesu8_buf_p,
3442 (lit_utf8_size_t) buf_size);
3443 } /* jerry_is_valid_cesu8_string */
3444
3445 /**
3446 * Allocate memory on the engine's heap.
3447 *
3448 * Note:
3449 * This function may take away memory from the executed JavaScript code.
3450 * If any other dynamic memory allocation API is available (e.g., libc
3451 * malloc), it should be used instead.
3452 *
3453 * @return allocated memory on success
3454 * NULL otherwise
3455 */
3456 void *
jerry_heap_alloc(size_t size)3457 jerry_heap_alloc (size_t size) /**< size of the memory block */
3458 {
3459 jerry_assert_api_available ();
3460
3461 return jmem_heap_alloc_block_null_on_error (size);
3462 } /* jerry_heap_alloc */
3463
3464 /**
3465 * Free memory allocated on the engine's heap.
3466 */
3467 void
jerry_heap_free(void * mem_p,size_t size)3468 jerry_heap_free (void *mem_p, /**< value returned by jerry_heap_alloc */
3469 size_t size) /**< same size as passed to jerry_heap_alloc */
3470 {
3471 jerry_assert_api_available ();
3472
3473 jmem_heap_free_block (mem_p, size);
3474 } /* jerry_heap_free */
3475
3476 /**
3477 * Create an external engine context.
3478 *
3479 * @return the pointer to the context.
3480 */
3481 jerry_context_t *
jerry_create_context(uint32_t heap_size,jerry_context_alloc_t alloc,void * cb_data_p)3482 jerry_create_context (uint32_t heap_size, /**< the size of heap */
3483 jerry_context_alloc_t alloc, /**< the alloc function */
3484 void *cb_data_p) /**< the cb_data for alloc function */
3485 {
3486 JERRY_UNUSED (heap_size);
3487
3488 #if ENABLED (JERRY_EXTERNAL_CONTEXT)
3489
3490 size_t total_size = sizeof (jerry_context_t) + JMEM_ALIGNMENT;
3491
3492 #if !ENABLED (JERRY_SYSTEM_ALLOCATOR)
3493 heap_size = JERRY_ALIGNUP (heap_size, JMEM_ALIGNMENT);
3494
3495 /* Minimum heap size is 1Kbyte. */
3496 if (heap_size < 1024)
3497 {
3498 return NULL;
3499 }
3500
3501 total_size += heap_size;
3502 #endif /* !ENABLED (JERRY_SYSTEM_ALLOCATOR) */
3503
3504 total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT);
3505
3506 jerry_context_t *context_p = (jerry_context_t *) alloc (total_size, cb_data_p);
3507
3508 if (context_p == NULL)
3509 {
3510 return NULL;
3511 }
3512
3513 memset (context_p, 0, total_size);
3514
3515 uintptr_t context_ptr = ((uintptr_t) context_p) + sizeof (jerry_context_t);
3516 context_ptr = JERRY_ALIGNUP (context_ptr, (uintptr_t) JMEM_ALIGNMENT);
3517
3518 uint8_t *byte_p = (uint8_t *) context_ptr;
3519
3520 #if !ENABLED (JERRY_SYSTEM_ALLOCATOR)
3521 context_p->heap_p = (jmem_heap_t *) byte_p;
3522 context_p->heap_size = heap_size;
3523 byte_p += heap_size;
3524 #endif /* !ENABLED (JERRY_SYSTEM_ALLOCATOR) */
3525
3526 JERRY_ASSERT (byte_p <= ((uint8_t *) context_p) + total_size);
3527
3528 JERRY_UNUSED (byte_p);
3529 return context_p;
3530
3531 #else /* !ENABLED (JERRY_EXTERNAL_CONTEXT) */
3532
3533 JERRY_UNUSED (alloc);
3534 JERRY_UNUSED (cb_data_p);
3535
3536 return NULL;
3537
3538 #endif /* ENABLED (JERRY_EXTERNAL_CONTEXT) */
3539 } /* jerry_create_context */
3540
3541 /**
3542 * If JERRY_VM_EXEC_STOP is enabled the callback passed to this function is
3543 * periodically called with the user_p argument. If frequency is greater
3544 * than 1, the callback is only called at every frequency ticks.
3545 */
3546 void
jerry_set_vm_exec_stop_callback(jerry_vm_exec_stop_callback_t stop_cb,void * user_p,uint32_t frequency)3547 jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< periodically called user function */
3548 void *user_p, /**< pointer passed to the function */
3549 uint32_t frequency) /**< frequency of the function call */
3550 {
3551 #if ENABLED (JERRY_VM_EXEC_STOP)
3552 if (frequency == 0)
3553 {
3554 frequency = 1;
3555 }
3556
3557 JERRY_CONTEXT (vm_exec_stop_frequency) = frequency;
3558 JERRY_CONTEXT (vm_exec_stop_counter) = frequency;
3559 JERRY_CONTEXT (vm_exec_stop_user_p) = user_p;
3560 JERRY_CONTEXT (vm_exec_stop_cb) = stop_cb;
3561 #else /* !ENABLED (JERRY_VM_EXEC_STOP) */
3562 JERRY_UNUSED (stop_cb);
3563 JERRY_UNUSED (user_p);
3564 JERRY_UNUSED (frequency);
3565 #endif /* ENABLED (JERRY_VM_EXEC_STOP) */
3566 } /* jerry_set_vm_exec_stop_callback */
3567
3568 /**
3569 * Get backtrace. The backtrace is an array of strings where
3570 * each string contains the position of the corresponding frame.
3571 * The array length is zero if the backtrace is not available.
3572 *
3573 * @return array value
3574 */
3575 jerry_value_t
jerry_get_backtrace(uint32_t max_depth)3576 jerry_get_backtrace (uint32_t max_depth) /**< depth limit of the backtrace */
3577 {
3578 return vm_get_backtrace (max_depth);
3579 } /* jerry_get_backtrace */
3580
3581 /**
3582 * Get the resource name (usually a file name) of the currently executed script or the given function object
3583 *
3584 * Note: returned value must be freed with jerry_release_value, when it is no longer needed
3585 *
3586 * @return JS string constructed from
3587 * - the currently executed function object's resource name, if the given value is undefined
3588 * - resource name of the function object, if the given value is a function object
3589 * - "<anonymous>", otherwise
3590 */
3591 jerry_value_t
jerry_get_resource_name(const jerry_value_t value)3592 jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */
3593 {
3594 #if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
3595 if (ecma_is_value_undefined (value))
3596 {
3597 if (JERRY_CONTEXT (vm_top_context_p) != NULL)
3598 {
3599 return ecma_copy_value (JERRY_CONTEXT (vm_top_context_p)->resource_name);
3600 }
3601 }
3602 #endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
3603 #if ENABLED (JERRY_LINE_INFO)
3604 else if (ecma_is_value_object (value))
3605 {
3606 ecma_object_t *obj_p = ecma_get_object_from_value (value);
3607
3608 if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION
3609 && !ecma_get_object_is_builtin (obj_p))
3610 {
3611 ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p;
3612
3613 const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
3614
3615 return ecma_copy_value (ecma_op_resource_name (bytecode_data_p));
3616 }
3617 }
3618 #endif /* ENABLED (JERRY_LINE_INFO) */
3619
3620 JERRY_UNUSED (value);
3621 return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
3622 } /* jerry_get_resource_name */
3623
3624 /**
3625 * Access the "new.target" value.
3626 *
3627 * The "new.target" value depends on the current call site. That is
3628 * this method will only have a function object result if, at the call site
3629 * it was called inside a constructor method invoked with "new".
3630 *
3631 * @return "undefined" - if at the call site it was not a constructor call.
3632 * function object - if the current call site is in a constructor call.
3633 */
3634 jerry_value_t
jerry_get_new_target(void)3635 jerry_get_new_target (void)
3636 {
3637 #if ENABLED (JERRY_ES2015)
3638 ecma_object_t *current_new_target = JERRY_CONTEXT (current_new_target);
3639
3640 if (current_new_target == NULL)
3641 {
3642 return jerry_create_undefined ();
3643 }
3644
3645 ecma_ref_object (current_new_target);
3646 return ecma_make_object_value (current_new_target);
3647 #else /* !ENABLED (JERRY_ES2015) */
3648 return jerry_create_undefined ();
3649 #endif /* ENABLED (JERRY_ES2015) */
3650 } /* jerry_get_new_target */
3651
3652 /**
3653 * Check if the given value is an ArrayBuffer object.
3654 *
3655 * @return true - if it is an ArrayBuffer object
3656 * false - otherwise
3657 */
3658 bool
jerry_value_is_arraybuffer(const jerry_value_t value)3659 jerry_value_is_arraybuffer (const jerry_value_t value) /**< value to check if it is an ArrayBuffer */
3660 {
3661 jerry_assert_api_available ();
3662
3663 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3664 return ecma_is_arraybuffer (value);
3665 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3666 JERRY_UNUSED (value);
3667 return false;
3668 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3669 } /* jerry_value_is_arraybuffer */
3670
3671 /**
3672 * Creates an ArrayBuffer object with the given length (size).
3673 *
3674 * Notes:
3675 * * the length is specified in bytes.
3676 * * returned value must be freed with jerry_release_value, when it is no longer needed.
3677 * * if the typed arrays are disabled this will return a TypeError.
3678 *
3679 * @return value of the constructed ArrayBuffer object
3680 */
3681 jerry_value_t
jerry_create_arraybuffer(const jerry_length_t size)3682 jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffer to create */
3683 {
3684 jerry_assert_api_available ();
3685
3686 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3687 return jerry_return (ecma_make_object_value (ecma_arraybuffer_new_object (size)));
3688 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3689 JERRY_UNUSED (size);
3690 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
3691 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3692 } /* jerry_create_arraybuffer */
3693
3694 /**
3695 * Creates an ArrayBuffer object with user specified buffer.
3696 *
3697 * Notes:
3698 * * the size is specified in bytes.
3699 * * the buffer passed should be at least the specified bytes big.
3700 * * if the typed arrays are disabled this will return a TypeError.
3701 * * if the size is zero or buffer_p is a null pointer this will return an empty ArrayBuffer.
3702 *
3703 * @return value of the construced ArrayBuffer object
3704 */
3705 jerry_value_t
jerry_create_arraybuffer_external(const jerry_length_t size,uint8_t * buffer_p,jerry_object_native_free_callback_t free_cb)3706 jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the buffer to used */
3707 uint8_t *buffer_p, /**< buffer to use as the ArrayBuffer's backing */
3708 jerry_object_native_free_callback_t free_cb) /**< buffer free callback */
3709 {
3710 jerry_assert_api_available ();
3711
3712 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3713 ecma_object_t *arraybuffer;
3714
3715 if (JERRY_UNLIKELY (size == 0 || buffer_p == NULL))
3716 {
3717 arraybuffer = ecma_arraybuffer_new_object_external (0, NULL, (ecma_object_native_free_callback_t) free_cb);
3718 }
3719 else
3720 {
3721 arraybuffer = ecma_arraybuffer_new_object_external (size,
3722 buffer_p,
3723 (ecma_object_native_free_callback_t) free_cb);
3724 }
3725
3726 return jerry_return (ecma_make_object_value (arraybuffer));
3727 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3728 JERRY_UNUSED (size);
3729 JERRY_UNUSED (buffer_p);
3730 JERRY_UNUSED (free_cb);
3731 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
3732 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3733 } /* jerry_create_arraybuffer_external */
3734
3735 /**
3736 * Copy bytes into the ArrayBuffer from a buffer.
3737 *
3738 * Note:
3739 * * if the object passed is not an ArrayBuffer will return 0.
3740 *
3741 * @return number of bytes copied into the ArrayBuffer.
3742 */
3743 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)3744 jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer */
3745 jerry_length_t offset, /**< start offset of the ArrayBuffer */
3746 const uint8_t *buf_p, /**< buffer to copy from */
3747 jerry_length_t buf_size) /**< number of bytes to copy from the buffer */
3748 {
3749 jerry_assert_api_available ();
3750
3751 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3752 if (!ecma_is_arraybuffer (value))
3753 {
3754 return 0;
3755 }
3756
3757 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3758 jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
3759
3760 if (offset >= length)
3761 {
3762 return 0;
3763 }
3764
3765 jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size);
3766
3767 if (copy_count > 0)
3768 {
3769 lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
3770
3771 memcpy ((void *) (mem_buffer_p + offset), (void *) buf_p, copy_count);
3772 }
3773
3774 return copy_count;
3775 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3776 JERRY_UNUSED (value);
3777 JERRY_UNUSED (offset);
3778 JERRY_UNUSED (buf_p);
3779 JERRY_UNUSED (buf_size);
3780 return 0;
3781 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3782 } /* jerry_arraybuffer_write */
3783
3784 /**
3785 * Copy bytes from a buffer into an ArrayBuffer.
3786 *
3787 * Note:
3788 * * if the object passed is not an ArrayBuffer will return 0.
3789 *
3790 * @return number of bytes read from the ArrayBuffer.
3791 */
3792 jerry_length_t
jerry_arraybuffer_read(const jerry_value_t value,jerry_length_t offset,uint8_t * buf_p,jerry_length_t buf_size)3793 jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer to read from */
3794 jerry_length_t offset, /**< start offset of the ArrayBuffer */
3795 uint8_t *buf_p, /**< destination buffer to copy to */
3796 jerry_length_t buf_size) /**< number of bytes to copy into the buffer */
3797 {
3798 jerry_assert_api_available ();
3799
3800 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3801 if (!ecma_is_arraybuffer (value))
3802 {
3803 return 0;
3804 }
3805
3806 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3807 jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
3808
3809 if (offset >= length)
3810 {
3811 return 0;
3812 }
3813
3814 jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size);
3815
3816 if (copy_count > 0)
3817 {
3818 lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
3819
3820 memcpy ((void *) buf_p, (void *) (mem_buffer_p + offset), copy_count);
3821 }
3822
3823 return copy_count;
3824 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3825 JERRY_UNUSED (value);
3826 JERRY_UNUSED (offset);
3827 JERRY_UNUSED (buf_p);
3828 JERRY_UNUSED (buf_size);
3829 return 0;
3830 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3831 } /* jerry_arraybuffer_read */
3832
3833 /**
3834 * Get the length (size) of the ArrayBuffer in bytes.
3835 *
3836 * Note:
3837 * This is the 'byteLength' property of an ArrayBuffer.
3838 *
3839 * @return the length of the ArrayBuffer in bytes.
3840 */
3841 jerry_length_t
jerry_get_arraybuffer_byte_length(const jerry_value_t value)3842 jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer */
3843 {
3844 jerry_assert_api_available ();
3845
3846 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3847 if (ecma_is_arraybuffer (value))
3848 {
3849 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3850 return ecma_arraybuffer_get_length (buffer_p);
3851 }
3852 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3853 JERRY_UNUSED (value);
3854 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3855 return 0;
3856 } /* jerry_get_arraybuffer_byte_length */
3857
3858 /**
3859 * Get a pointer for the start of the ArrayBuffer.
3860 *
3861 * Note:
3862 * * This is a high-risk operation as the bounds are not checked
3863 * when accessing the pointer elements.
3864 *
3865 * @return pointer to the back-buffer of the ArrayBuffer.
3866 * pointer is NULL if the parameter is not an ArrayBuffer
3867 */
3868 uint8_t *
jerry_get_arraybuffer_pointer(const jerry_value_t array_buffer)3869 jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buffer to use */
3870 {
3871 jerry_assert_api_available ();
3872
3873 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3874 if (ecma_is_value_error_reference (array_buffer)
3875 || !ecma_is_arraybuffer (array_buffer))
3876 {
3877 return NULL;
3878 }
3879
3880 ecma_object_t *buffer_p = ecma_get_object_from_value (array_buffer);
3881 lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
3882 return (uint8_t *const) mem_buffer_p;
3883 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3884 JERRY_UNUSED (array_buffer);
3885 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3886
3887 return NULL;
3888 } /* jerry_get_arraybuffer_pointer */
3889
3890 /**
3891 * Get if the ArrayBuffer is detachable.
3892 *
3893 * @return boolean value - if success
3894 * value marked with error flag - otherwise
3895 */
3896 jerry_value_t
jerry_is_arraybuffer_detachable(const jerry_value_t value)3897 jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
3898 {
3899 jerry_assert_api_available ();
3900
3901 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3902 if (ecma_is_arraybuffer (value))
3903 {
3904 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3905 return ecma_arraybuffer_is_detachable (buffer_p) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
3906 }
3907 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3908 JERRY_UNUSED (value);
3909 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3910 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
3911 } /* jerry_is_arraybuffer_detachable */
3912
3913 /**
3914 * Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
3915 * This operation requires the ArrayBuffer to be external that created by
3916 * `jerry_create_arraybuffer_external`.
3917 *
3918 * @return null value - if success
3919 * value marked with error flag - otherwise
3920 */
3921 jerry_value_t
jerry_detach_arraybuffer(const jerry_value_t value)3922 jerry_detach_arraybuffer (const jerry_value_t value) /**< ArrayBuffer */
3923 {
3924 jerry_assert_api_available ();
3925
3926 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3927 if (ecma_is_arraybuffer (value))
3928 {
3929 ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3930 bool detached = ecma_arraybuffer_detach (buffer_p);
3931 if (!detached)
3932 {
3933 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects a detachable ArrayBuffer.")));
3934 }
3935 return ECMA_VALUE_NULL;
3936 }
3937 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3938 JERRY_UNUSED (value);
3939 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3940 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
3941 } /* jerry_detach_arraybuffer */
3942
3943 /**
3944 * DataView related functions
3945 */
3946
3947 /**
3948 * Creates a DataView object with the given ArrayBuffer, ByteOffset and ByteLength arguments.
3949 *
3950 * Notes:
3951 * * returned value must be freed with jerry_release_value, when it is no longer needed.
3952 * * if the DataView bulitin is disabled this will return a TypeError.
3953 *
3954 * @return value of the constructed DataView object - if success
3955 * created error - otherwise
3956 */
3957 jerry_value_t
jerry_create_dataview(const jerry_value_t array_buffer,const jerry_length_t byte_offset,const jerry_length_t byte_length)3958 jerry_create_dataview (const jerry_value_t array_buffer, /**< arraybuffer to create DataView from */
3959 const jerry_length_t byte_offset, /**< offset in bytes, to the first byte in the buffer */
3960 const jerry_length_t byte_length) /**< number of elements in the byte array */
3961 {
3962 jerry_assert_api_available ();
3963
3964 #if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
3965 if (ecma_is_value_error_reference (array_buffer))
3966 {
3967 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
3968 }
3969
3970 ecma_value_t arguments_p[3] =
3971 {
3972 array_buffer,
3973 ecma_make_uint32_value (byte_offset),
3974 ecma_make_uint32_value (byte_length)
3975 };
3976
3977 return jerry_return (ecma_op_dataview_create (arguments_p, 3));
3978 #else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
3979 JERRY_UNUSED (array_buffer);
3980 JERRY_UNUSED (byte_offset);
3981 JERRY_UNUSED (byte_length);
3982 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported.")));
3983 #endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */
3984 } /* jerry_create_dataview */
3985
3986 /**
3987 * Check if the given value is a DataView object.
3988 *
3989 * @return true - if it is a DataView object
3990 * false - otherwise
3991 */
3992 bool
jerry_value_is_dataview(const jerry_value_t value)3993 jerry_value_is_dataview (const jerry_value_t value) /**< value to check if it is a DataView object */
3994 {
3995 jerry_assert_api_available ();
3996
3997 #if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
3998 return ecma_is_dataview (value);
3999 #else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
4000 JERRY_UNUSED (value);
4001 return false;
4002 #endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */
4003 } /* jerry_value_is_dataview */
4004
4005 /**
4006 * Get the underlying ArrayBuffer from a DataView.
4007 *
4008 * Additionally the byteLength and byteOffset properties are also returned
4009 * which were specified when the DataView was created.
4010 *
4011 * Note:
4012 * the returned value must be freed with a jerry_release_value call
4013 *
4014 * @return ArrayBuffer of a DataView
4015 * TypeError if the object is not a DataView.
4016 */
4017 jerry_value_t
jerry_get_dataview_buffer(const jerry_value_t value,jerry_length_t * byte_offset,jerry_length_t * byte_length)4018 jerry_get_dataview_buffer (const jerry_value_t value, /**< DataView to get the arraybuffer from */
4019 jerry_length_t *byte_offset, /**< [out] byteOffset property */
4020 jerry_length_t *byte_length) /**< [out] byteLength property */
4021 {
4022 jerry_assert_api_available ();
4023
4024 #if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
4025 if (ecma_is_value_error_reference (value))
4026 {
4027 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
4028 }
4029
4030 ecma_dataview_object_t *dataview_p = ecma_op_dataview_get_object (value);
4031
4032 if (JERRY_UNLIKELY (dataview_p == NULL))
4033 {
4034 return ecma_create_error_reference_from_context ();
4035 }
4036
4037 if (byte_offset != NULL)
4038 {
4039 *byte_offset = dataview_p->byte_offset;
4040 }
4041
4042 if (byte_length != NULL)
4043 {
4044 *byte_length = dataview_p->header.u.class_prop.u.length;
4045 }
4046
4047 ecma_object_t *arraybuffer_p = dataview_p->buffer_p;
4048 ecma_ref_object (arraybuffer_p);
4049
4050 return ecma_make_object_value (arraybuffer_p);
4051 #else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
4052 JERRY_UNUSED (value);
4053 JERRY_UNUSED (byte_offset);
4054 JERRY_UNUSED (byte_length);
4055 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported.")));
4056 #endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */
4057 } /* jerry_get_dataview_buffer */
4058
4059 /**
4060 * TypedArray related functions
4061 */
4062
4063 /**
4064 * Check if the given value is a TypedArray object.
4065 *
4066 * @return true - if it is a TypedArray object
4067 * false - otherwise
4068 */
4069 bool
jerry_value_is_typedarray(jerry_value_t value)4070 jerry_value_is_typedarray (jerry_value_t value) /**< value to check if it is a TypedArray */
4071 {
4072 jerry_assert_api_available ();
4073
4074 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4075 return ecma_is_typedarray (value);
4076 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4077 JERRY_UNUSED (value);
4078 return false;
4079 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4080 } /* jerry_value_is_typedarray */
4081
4082 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4083 /**
4084 * TypedArray mapping type
4085 */
4086 typedef struct
4087 {
4088 jerry_typedarray_type_t api_type; /**< api type */
4089 ecma_builtin_id_t prototype_id; /**< prototype ID */
4090 ecma_typedarray_type_t id; /**< typedArray ID */
4091 uint8_t element_size_shift; /**< element size shift */
4092 } jerry_typedarray_mapping_t;
4093
4094 /**
4095 * List of TypedArray mappings
4096 */
4097 static jerry_typedarray_mapping_t jerry_typedarray_mappings[] =
4098 {
4099 #define TYPEDARRAY_ENTRY(NAME, LIT_NAME, SIZE_SHIFT) \
4100 { JERRY_TYPEDARRAY_ ## NAME, ECMA_BUILTIN_ID_ ## NAME ## ARRAY_PROTOTYPE, \
4101 ECMA_ ## LIT_NAME ## _ARRAY, SIZE_SHIFT }
4102
4103 TYPEDARRAY_ENTRY (UINT8, UINT8, 0),
4104 TYPEDARRAY_ENTRY (UINT8CLAMPED, UINT8_CLAMPED, 0),
4105 TYPEDARRAY_ENTRY (INT8, INT8, 0),
4106 TYPEDARRAY_ENTRY (UINT16, UINT16, 1),
4107 TYPEDARRAY_ENTRY (INT16, INT16, 1),
4108 TYPEDARRAY_ENTRY (UINT32, UINT32, 2),
4109 TYPEDARRAY_ENTRY (INT32, INT32, 2),
4110 TYPEDARRAY_ENTRY (FLOAT32, FLOAT32, 2),
4111 #if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
4112 TYPEDARRAY_ENTRY (FLOAT64, FLOAT64, 3),
4113 #endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
4114
4115 #undef TYPEDARRAY_ENTRY
4116 };
4117
4118 /**
4119 * Helper function to get the TypedArray prototype, typedArray id, and element size shift
4120 * information.
4121 *
4122 * @return true - if the TypedArray information was found
4123 * false - if there is no such TypedArray type
4124 */
4125 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)4126 jerry_typedarray_find_by_type (jerry_typedarray_type_t type_name, /**< type of the TypedArray */
4127 ecma_builtin_id_t *prototype_id, /**< [out] found prototype object id */
4128 ecma_typedarray_type_t *id, /**< [out] found typedArray id */
4129 uint8_t *element_size_shift) /**< [out] found element size shift value */
4130 {
4131 JERRY_ASSERT (prototype_id != NULL);
4132 JERRY_ASSERT (id != NULL);
4133 JERRY_ASSERT (element_size_shift != NULL);
4134
4135 for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
4136 {
4137 if (type_name == jerry_typedarray_mappings[i].api_type)
4138 {
4139 *prototype_id = jerry_typedarray_mappings[i].prototype_id;
4140 *id = jerry_typedarray_mappings[i].id;
4141 *element_size_shift = jerry_typedarray_mappings[i].element_size_shift;
4142 return true;
4143 }
4144 }
4145
4146 return false;
4147 } /* jerry_typedarray_find_by_type */
4148
4149 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4150
4151 /**
4152 * Create a TypedArray object with a given type and length.
4153 *
4154 * Notes:
4155 * * returns TypeError if an incorrect type (type_name) is specified.
4156 * * byteOffset property will be set to 0.
4157 * * byteLength property will be a multiple of the length parameter (based on the type).
4158 *
4159 * @return - new TypedArray object
4160 */
4161 jerry_value_t
jerry_create_typedarray(jerry_typedarray_type_t type_name,jerry_length_t length)4162 jerry_create_typedarray (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
4163 jerry_length_t length) /**< element count of the new TypedArray */
4164 {
4165 jerry_assert_api_available ();
4166
4167 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4168 ecma_builtin_id_t prototype_id = 0;
4169 ecma_typedarray_type_t id = 0;
4170 uint8_t element_size_shift = 0;
4171
4172 if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift))
4173 {
4174 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
4175 }
4176
4177 ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
4178
4179 ecma_value_t array_value = ecma_typedarray_create_object_with_length (length,
4180 NULL,
4181 prototype_obj_p,
4182 element_size_shift,
4183 id);
4184
4185 JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value));
4186
4187 return array_value;
4188 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4189 JERRY_UNUSED (type_name);
4190 JERRY_UNUSED (length);
4191 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
4192 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4193 } /* jerry_create_typedarray */
4194
4195 /**
4196 * Create a TypedArray object using the given arraybuffer and size information.
4197 *
4198 * Notes:
4199 * * returns TypeError if an incorrect type (type_name) is specified.
4200 * * this is the 'new %TypedArray%(arraybuffer, byteOffset, length)' equivalent call.
4201 *
4202 * @return - new TypedArray object
4203 */
4204 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)4205 jerry_create_typedarray_for_arraybuffer_sz (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
4206 const jerry_value_t arraybuffer, /**< ArrayBuffer to use */
4207 jerry_length_t byte_offset, /**< offset for the ArrayBuffer */
4208 jerry_length_t length) /**< number of elements to use from ArrayBuffer */
4209 {
4210 jerry_assert_api_available ();
4211
4212 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4213 if (ecma_is_value_error_reference (arraybuffer))
4214 {
4215 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4216 }
4217
4218 ecma_builtin_id_t prototype_id = 0;
4219 ecma_typedarray_type_t id = 0;
4220 uint8_t element_size_shift = 0;
4221
4222 if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift))
4223 {
4224 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
4225 }
4226
4227 if (!ecma_is_arraybuffer (arraybuffer))
4228 {
4229 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an ArrayBuffer")));
4230 }
4231
4232 ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
4233 ecma_value_t arguments_p[3] =
4234 {
4235 arraybuffer,
4236 ecma_make_uint32_value (byte_offset),
4237 ecma_make_uint32_value (length)
4238 };
4239
4240 ecma_value_t array_value = ecma_op_create_typedarray (arguments_p, 3, prototype_obj_p, element_size_shift, id);
4241 ecma_free_value (arguments_p[1]);
4242 ecma_free_value (arguments_p[2]);
4243
4244 return jerry_return (array_value);
4245 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4246 JERRY_UNUSED (type_name);
4247 JERRY_UNUSED (arraybuffer);
4248 JERRY_UNUSED (byte_offset);
4249 JERRY_UNUSED (length);
4250 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
4251 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4252 } /* jerry_create_typedarray_for_arraybuffer_sz */
4253
4254 /**
4255 * Create a TypedArray object using the given arraybuffer and size information.
4256 *
4257 * Notes:
4258 * * returns TypeError if an incorrect type (type_name) is specified.
4259 * * this is the 'new %TypedArray%(arraybuffer)' equivalent call.
4260 *
4261 * @return - new TypedArray object
4262 */
4263 jerry_value_t
jerry_create_typedarray_for_arraybuffer(jerry_typedarray_type_t type_name,const jerry_value_t arraybuffer)4264 jerry_create_typedarray_for_arraybuffer (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
4265 const jerry_value_t arraybuffer) /**< ArrayBuffer to use */
4266 {
4267 jerry_assert_api_available ();
4268
4269 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4270 if (ecma_is_value_error_reference (arraybuffer))
4271 {
4272 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4273 }
4274
4275 jerry_length_t byteLength = jerry_get_arraybuffer_byte_length (arraybuffer);
4276 return jerry_create_typedarray_for_arraybuffer_sz (type_name, arraybuffer, 0, byteLength);
4277 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4278 JERRY_UNUSED (type_name);
4279 JERRY_UNUSED (arraybuffer);
4280 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
4281 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4282 } /* jerry_create_typedarray_for_arraybuffer */
4283
4284 /**
4285 * Get the type of the TypedArray.
4286 *
4287 * @return - type of the TypedArray
4288 * - JERRY_TYPEDARRAY_INVALID if the argument is not a TypedArray
4289 */
4290 jerry_typedarray_type_t
jerry_get_typedarray_type(jerry_value_t value)4291 jerry_get_typedarray_type (jerry_value_t value) /**< object to get the TypedArray type */
4292 {
4293 jerry_assert_api_available ();
4294
4295 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4296 if (!ecma_is_typedarray (value))
4297 {
4298 return JERRY_TYPEDARRAY_INVALID;
4299 }
4300
4301 ecma_object_t *array_p = ecma_get_object_from_value (value);
4302 ecma_typedarray_type_t class_type = ecma_get_typedarray_id (array_p);
4303
4304 for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
4305 {
4306 if (class_type == jerry_typedarray_mappings[i].id)
4307 {
4308 return jerry_typedarray_mappings[i].api_type;
4309 }
4310 }
4311 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4312 JERRY_UNUSED (value);
4313 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4314
4315 return JERRY_TYPEDARRAY_INVALID;
4316 } /* jerry_get_typedarray_type */
4317
4318 /**
4319 * Get the element count of the TypedArray.
4320 *
4321 * @return length of the TypedArray.
4322 */
4323 jerry_length_t
jerry_get_typedarray_length(jerry_value_t value)4324 jerry_get_typedarray_length (jerry_value_t value) /**< TypedArray to query */
4325 {
4326 jerry_assert_api_available ();
4327
4328 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4329 if (ecma_is_typedarray (value))
4330 {
4331 ecma_object_t *array_p = ecma_get_object_from_value (value);
4332 return ecma_typedarray_get_length (array_p);
4333 }
4334 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4335 JERRY_UNUSED (value);
4336 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4337
4338 return 0;
4339 } /* jerry_get_typedarray_length */
4340
4341 /**
4342 * Get the underlying ArrayBuffer from a TypedArray.
4343 *
4344 * Additionally the byteLength and byteOffset properties are also returned
4345 * which were specified when the TypedArray was created.
4346 *
4347 * Note:
4348 * the returned value must be freed with a jerry_release_value call
4349 *
4350 * @return ArrayBuffer of a TypedArray
4351 * TypeError if the object is not a TypedArray.
4352 */
4353 jerry_value_t
jerry_get_typedarray_buffer(jerry_value_t value,jerry_length_t * byte_offset,jerry_length_t * byte_length)4354 jerry_get_typedarray_buffer (jerry_value_t value, /**< TypedArray to get the arraybuffer from */
4355 jerry_length_t *byte_offset, /**< [out] byteOffset property */
4356 jerry_length_t *byte_length) /**< [out] byteLength property */
4357 {
4358 jerry_assert_api_available ();
4359
4360 #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
4361 if (!ecma_is_typedarray (value))
4362 {
4363 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Object is not a TypedArray.")));
4364 }
4365
4366 ecma_object_t *array_p = ecma_get_object_from_value (value);
4367 uint8_t shift = ecma_typedarray_get_element_size_shift (array_p);
4368
4369 if (byte_length != NULL)
4370 {
4371 *byte_length = (jerry_length_t) (ecma_typedarray_get_length (array_p) << shift);
4372 }
4373
4374 if (byte_offset != NULL)
4375 {
4376 *byte_offset = (jerry_length_t) ecma_typedarray_get_offset (array_p);
4377 }
4378
4379 ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_p);
4380 ecma_ref_object (arraybuffer_p);
4381 return jerry_return (ecma_make_object_value (arraybuffer_p));
4382 #else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4383 JERRY_UNUSED (value);
4384 JERRY_UNUSED (byte_length);
4385 JERRY_UNUSED (byte_offset);
4386 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray is not supported.")));
4387 #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
4388 } /* jerry_get_typedarray_buffer */
4389
4390 /**
4391 * Create an object from JSON
4392 *
4393 * Note:
4394 * The returned value must be freed with jerry_release_value
4395 * @return jerry_value_t from json formated string or an error massage
4396 */
4397 jerry_value_t
jerry_json_parse(const jerry_char_t * string_p,jerry_size_t string_size)4398 jerry_json_parse (const jerry_char_t *string_p, /**< json string */
4399 jerry_size_t string_size) /**< json string size */
4400 {
4401 jerry_assert_api_available ();
4402
4403 #if ENABLED (JERRY_BUILTIN_JSON)
4404 ecma_value_t ret_value = ecma_builtin_json_parse_buffer (string_p, string_size);
4405
4406 if (ecma_is_value_undefined (ret_value))
4407 {
4408 ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON string parse error.")));
4409 }
4410
4411 return ret_value;
4412 #else /* !ENABLED (JERRY_BUILTIN_JSON) */
4413 JERRY_UNUSED (string_p);
4414 JERRY_UNUSED (string_size);
4415
4416 return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
4417 #endif /* ENABLED (JERRY_BUILTIN_JSON) */
4418 } /* jerry_json_parse */
4419
4420 /**
4421 * Create a Json formated string from an object
4422 *
4423 * Note:
4424 * The returned value must be freed with jerry_release_value
4425 * @return json formated jerry_value_t or an error massage
4426 */
4427 jerry_value_t
jerry_json_stringify(const jerry_value_t object_to_stringify)4428 jerry_json_stringify (const jerry_value_t object_to_stringify) /**< a jerry_object_t to stringify */
4429 {
4430 jerry_assert_api_available ();
4431 #if ENABLED (JERRY_BUILTIN_JSON)
4432 ecma_value_t ret_value = ecma_builtin_json_string_from_object (object_to_stringify);
4433
4434 if (ecma_is_value_error_reference (object_to_stringify))
4435 {
4436 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4437 }
4438
4439 if (ecma_is_value_undefined (ret_value))
4440 {
4441 ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON stringify error.")));
4442 }
4443
4444 return ret_value;
4445 #else /* ENABLED (JERRY_BUILTIN_JSON) */
4446 JERRY_UNUSED (object_to_stringify);
4447
4448 return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
4449 #endif /* ENABLED (JERRY_BUILTIN_JSON) */
4450 } /* jerry_json_stringify */
4451
4452 /**
4453 * Create a container type specified in jerry_container_type_t.
4454 * The container can be created with a list of arguments, which will be passed to the container constructor to be
4455 * inserted to the container.
4456 *
4457 * Note:
4458 * The returned value must be freed with jerry_release_value
4459 * @return jerry_value_t representing a container with the given type.
4460 */
4461 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)4462 jerry_create_container (jerry_container_type_t container_type, /**< Type of the container */
4463 const jerry_value_t *arguments_list_p, /**< arguments list */
4464 jerry_length_t arguments_list_len) /**< Length of arguments list */
4465 {
4466 jerry_assert_api_available ();
4467
4468 #if ENABLED (JERRY_ES2015_BUILTIN_CONTAINER)
4469 for (jerry_length_t i = 0; i < arguments_list_len; i++)
4470 {
4471 if (ecma_is_value_error_reference (arguments_list_p[i]))
4472 {
4473 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
4474 }
4475 }
4476
4477 lit_magic_string_id_t lit_id;
4478 ecma_builtin_id_t proto_id;
4479 ecma_builtin_id_t ctor_id;
4480
4481 switch (container_type)
4482 {
4483 #if ENABLED (JERRY_ES2015_BUILTIN_MAP)
4484 case JERRY_CONTAINER_TYPE_MAP:
4485 {
4486 lit_id = LIT_MAGIC_STRING_MAP_UL;
4487 proto_id = ECMA_BUILTIN_ID_MAP_PROTOTYPE;
4488 ctor_id = ECMA_BUILTIN_ID_MAP;
4489 break;
4490 }
4491 #endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
4492 #if ENABLED (JERRY_ES2015_BUILTIN_SET)
4493 case JERRY_CONTAINER_TYPE_SET:
4494 {
4495 lit_id = LIT_MAGIC_STRING_SET_UL;
4496 proto_id = ECMA_BUILTIN_ID_SET_PROTOTYPE;
4497 ctor_id = ECMA_BUILTIN_ID_SET;
4498 break;
4499 }
4500 #endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
4501 #if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP)
4502 case JERRY_CONTAINER_TYPE_WEAKMAP:
4503 {
4504 lit_id = LIT_MAGIC_STRING_WEAKMAP_UL;
4505 proto_id = ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE;
4506 ctor_id = ECMA_BUILTIN_ID_WEAKMAP;
4507 break;
4508 }
4509 #endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
4510 #if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
4511 case JERRY_CONTAINER_TYPE_WEAKSET:
4512 {
4513 lit_id = LIT_MAGIC_STRING_WEAKSET_UL;
4514 proto_id = ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE;
4515 ctor_id = ECMA_BUILTIN_ID_WEAKSET;
4516 break;
4517 }
4518 #endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
4519 default:
4520 {
4521 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Invalid container type.")));
4522 }
4523 }
4524 ecma_object_t * old_new_target_p = JERRY_CONTEXT (current_new_target);
4525
4526 if (old_new_target_p == NULL)
4527 {
4528 JERRY_CONTEXT (current_new_target) = ecma_builtin_get (ctor_id);
4529 }
4530
4531 ecma_value_t container_value = ecma_op_container_create (arguments_list_p,
4532 arguments_list_len,
4533 lit_id,
4534 proto_id);
4535
4536 JERRY_CONTEXT (current_new_target) = old_new_target_p;
4537 return container_value;
4538 #else /* !ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4539 JERRY_UNUSED (arguments_list_p);
4540 JERRY_UNUSED (arguments_list_len);
4541 JERRY_UNUSED (container_type);
4542 return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Containers are disabled.")));
4543 #endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4544 } /* jerry_create_container */
4545
4546 /**
4547 * Get the type of the given container object.
4548 *
4549 * @return Corresponding type to the given container object.
4550 */
4551 jerry_container_type_t
jerry_get_container_type(const jerry_value_t value)4552 jerry_get_container_type (const jerry_value_t value) /**< the container object */
4553 {
4554 jerry_assert_api_available ();
4555
4556 #if ENABLED (JERRY_ES2015_BUILTIN_CONTAINER)
4557 if (ecma_is_value_object (value))
4558 {
4559 ecma_object_t *obj_p = ecma_get_object_from_value (value);
4560
4561 if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS)
4562 {
4563 uint16_t type = ((ecma_extended_object_t *) obj_p)->u.class_prop.class_id;
4564
4565 switch (type)
4566 {
4567 #if ENABLED (JERRY_ES2015_BUILTIN_MAP)
4568 case LIT_MAGIC_STRING_MAP_UL:
4569 {
4570 return JERRY_CONTAINER_TYPE_MAP;
4571 }
4572 #endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
4573 #if ENABLED (JERRY_ES2015_BUILTIN_SET)
4574 case LIT_MAGIC_STRING_SET_UL:
4575 {
4576 return JERRY_CONTAINER_TYPE_SET;
4577 }
4578 #endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
4579 #if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP)
4580 case LIT_MAGIC_STRING_WEAKMAP_UL:
4581 {
4582 return JERRY_CONTAINER_TYPE_WEAKMAP;
4583 }
4584 #endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
4585 #if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
4586 case LIT_MAGIC_STRING_WEAKSET_UL:
4587 {
4588 return JERRY_CONTAINER_TYPE_WEAKSET;
4589 }
4590 #endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
4591 default:
4592 {
4593 return JERRY_CONTAINER_TYPE_INVALID;
4594 }
4595 }
4596 }
4597 }
4598
4599 #else /* !ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4600 JERRY_UNUSED (value);
4601 #endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
4602 return JERRY_CONTAINER_TYPE_INVALID;
4603 } /* jerry_get_container_type */
4604
4605 #if defined(JERRY_HEAPDUMP)
JerryHeapdumpRun(const char * filepath)4606 void JerryHeapdumpRun(const char* filepath)
4607 {
4608 SetHeapdumpTraring(true);
4609 LogHeapdumpInit(filepath);
4610 LogHeapdump("[\n");
4611 DumpInfoObject(ecma_builtin_get_global(), HEAPDUMP_OBJECT_GLOBAL);
4612 DumpInfoObject(ecma_get_global_environment(), HEAPDUMP_OBJECT_GLOBAL);
4613 ecma_gc_run();
4614 LogHeapdump("{}]\n");
4615 SetHeapdumpTraring(false);
4616 LogHeapdumpClose();
4617 }
4618 #endif
4619
4620 #if defined(JERRY_REF_TRACKER)
JerryRefTrackerStart(const char * filepath)4621 void JerryRefTrackerStart(const char* filepath)
4622 {
4623 SetRefTrackerEnabled(true);
4624 LogTrackerInit(filepath);
4625 }
4626 #endif
4627
4628 #if defined(JERRY_REF_TRACKER)
JerryRefTrackerStop(void)4629 void JerryRefTrackerStop(void)
4630 {
4631 SetRefTrackerEnabled(false);
4632 LogTrackerClose();
4633 }
4634 #endif
4635
4636 /**
4637 * @}
4638 */
4639