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