diff --git a/meson.build b/meson.build index 5def82ab..23fc4fdf 100644 --- a/meson.build +++ b/meson.build @@ -56,6 +56,11 @@ endif if all_loaders or get_option('loaders').contains('lottie') == true config_h.set10('THORVG_LOTTIE_LOADER_SUPPORT', true) + #Experimental feature, enable it manually + lottie_expressions = false + if lottie_expressions + config_h.set10('THORVG_LOTTIE_EXPRESSIONS_SUPPORT', false) + endif endif if all_loaders or get_option('loaders').contains('ttf') == true diff --git a/src/loaders/lottie/jerryscript/jerry-core/api/jerryscript.cpp b/src/loaders/lottie/jerryscript/jerry-core/api/jerryscript.cpp new file mode 100644 index 00000000..3f0fb2ec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/api/jerryscript.cpp @@ -0,0 +1,6847 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerryscript.h" + +#include +#include +#include + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-container-object.h" +#include "ecma-dataview-object.h" +#include "ecma-errors.h" +#include "ecma-eval.h" +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-init-finalize.h" +#include "ecma-iterator-object.h" +#include "ecma-lex-env.h" +#include "ecma-line-info.h" +#include "ecma-literal-storage.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" +#include "ecma-regexp-object.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-symbol-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt.h" +#include "js-parser.h" +#include "lit-char-helpers.h" +#include "opcodes.h" +#include "re-compiler.h" + +JERRY_STATIC_ASSERT ((sizeof (jerry_value_t) == sizeof (ecma_value_t)), + size_of_jerry_value_t_must_be_equal_to_size_of_ecma_value_t); + +#if JERRY_BUILTIN_REGEXP +JERRY_STATIC_ASSERT (((int) RE_FLAG_GLOBAL == (int) JERRY_REGEXP_FLAG_GLOBAL) + && ((int) RE_FLAG_MULTILINE == (int) JERRY_REGEXP_FLAG_MULTILINE) + && ((int) RE_FLAG_IGNORE_CASE == (int) JERRY_REGEXP_FLAG_IGNORE_CASE) + && ((int) RE_FLAG_STICKY == (int) JERRY_REGEXP_FLAG_STICKY) + && ((int) RE_FLAG_UNICODE == (int) JERRY_REGEXP_FLAG_UNICODE) + && ((int) RE_FLAG_DOTALL == (int) JERRY_REGEXP_FLAG_DOTALL), + re_flags_t_must_be_equal_to_jerry_regexp_flags_t); +#endif /* JERRY_BUILTIN_REGEXP */ + +/* The internal ECMA_PROMISE_STATE_* values are "one byte away" from the API values */ +JERRY_STATIC_ASSERT (((int) ECMA_PROMISE_IS_PENDING == (int) JERRY_PROMISE_STATE_PENDING) + && ((int) ECMA_PROMISE_IS_FULFILLED == (int) JERRY_PROMISE_STATE_FULFILLED), + promise_internal_state_matches_external); + +/** + * Offset between internal and external arithmetic operator types + */ +#define ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET (JERRY_BIN_OP_SUB - NUMBER_ARITHMETIC_SUBTRACTION) + +JERRY_STATIC_ASSERT (((NUMBER_ARITHMETIC_SUBTRACTION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_SUB) + && ((NUMBER_ARITHMETIC_MULTIPLICATION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) + == JERRY_BIN_OP_MUL) + && ((NUMBER_ARITHMETIC_DIVISION + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_DIV) + && ((NUMBER_ARITHMETIC_REMAINDER + ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET) == JERRY_BIN_OP_REM), + number_arithmetics_operation_type_matches_external); + +#if !JERRY_PARSER && !JERRY_SNAPSHOT_EXEC +#error "JERRY_SNAPSHOT_EXEC must be enabled if JERRY_PARSER is disabled!" +#endif /* !JERRY_PARSER && !JERRY_SNAPSHOT_EXEC */ + +/** \addtogroup jerry Jerry engine interface + * @{ + */ + +/** + * Assert that it is correct to call API in current state. + * + * Note: + * By convention, there are some states when API could not be invoked. + * + * The API can be and only be invoked when the ECMA_STATUS_API_ENABLED + * flag is set. + * + * This procedure checks whether the API is available, and terminates + * the engine if it is unavailable. Otherwise it is a no-op. + * + * Note: + * The API could not be invoked in the following cases: + * - before jerry_init and after jerry_cleanup + * - between enter to and return from a native free callback + * + * @return void + */ +static inline void +jerry_assert_api_enabled (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (status_flags) & ECMA_STATUS_API_ENABLED); +} /* jerry_assert_api_enabled */ + +/** + * Turn on API availability + * + * @return void + */ +static inline void +jerry_api_enable (void) +{ +#ifndef JERRY_NDEBUG + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_API_ENABLED; +#endif /* JERRY_NDEBUG */ +} /* jerry_make_api_available */ + +/** + * Turn off API availability + * + * @return void + */ +static inline void +jerry_api_disable (void) +{ +#ifndef JERRY_NDEBUG + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_API_ENABLED; +#endif /* JERRY_NDEBUG */ +} /* jerry_make_api_unavailable */ + +/** + * Create an API compatible return value. + * + * @return return value for Jerry API functions + */ +static jerry_value_t +jerry_return (const jerry_value_t value) /**< return value */ +{ + if (ECMA_IS_VALUE_ERROR (value)) + { + return ecma_create_exception_from_context (); + } + + return value; +} /* jerry_return */ + +/** + * Jerry engine initialization + */ +void +jerry_init (jerry_init_flag_t flags) /**< combination of Jerry flags */ +{ +#if JERRY_EXTERNAL_CONTEXT + size_t total_size = jerry_port_context_alloc (sizeof (jerry_context_t)); + JERRY_UNUSED (total_size); +#endif /* JERRY_EXTERNAL_CONTEXT */ + + jerry_context_t *context_p = &JERRY_CONTEXT_STRUCT; + memset (context_p, 0, sizeof (jerry_context_t)); + +#if JERRY_EXTERNAL_CONTEXT && !JERRY_SYSTEM_ALLOCATOR + uint32_t heap_start_offset = JERRY_ALIGNUP (sizeof (jerry_context_t), JMEM_ALIGNMENT); + uint8_t *heap_p = ((uint8_t *) context_p) + heap_start_offset; + uint32_t heap_size = JERRY_ALIGNDOWN (total_size - heap_start_offset, JMEM_ALIGNMENT); + + JERRY_ASSERT (heap_p + heap_size <= ((uint8_t *) context_p) + total_size); + + context_p->heap_p = (jmem_heap_t *) heap_p; + context_p->heap_size = heap_size; +#endif /* JERRY_EXTERNAL_CONTEXT && !JERRY_SYSTEM_ALLOCATOR */ + + JERRY_CONTEXT (jerry_init_flags) = flags; + + jerry_api_enable (); + + jmem_init (); + ecma_init (); +} /* jerry_init */ + +/** + * Terminate Jerry engine + */ +void +jerry_cleanup (void) +{ + for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p); this_p != NULL; this_p = this_p->next_p) + { + if (this_p->manager_p->deinit_cb) + { + void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL; + this_p->manager_p->deinit_cb (data); + } + } + + ecma_free_all_enqueued_jobs (); + ecma_finalize (); + jerry_api_disable (); + + for (jerry_context_data_header_t *this_p = JERRY_CONTEXT (context_data_p), *next_p = NULL; this_p != NULL; + this_p = next_p) + { + next_p = this_p->next_p; + + if (this_p->manager_p->finalize_cb) + { + void *data = (this_p->manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (this_p) : NULL; + this_p->manager_p->finalize_cb (data); + } + + jmem_heap_free_block (this_p, sizeof (jerry_context_data_header_t) + this_p->manager_p->bytes_needed); + } + + jmem_finalize (); +#if JERRY_EXTERNAL_CONTEXT + jerry_port_context_free (); +#endif /* JERRY_EXTERNAL_CONTEXT */ +} /* jerry_cleanup */ + +/** + * Retrieve a context data item, or create a new one. + * + * @param manager_p pointer to the manager whose context data item should be returned. + * + * @return a pointer to the user-provided context-specific data item for the given manager, creating such a pointer if + * none was found. + */ +void * +jerry_context_data (const jerry_context_data_manager_t *manager_p) +{ + void *ret = NULL; + jerry_context_data_header_t *item_p; + + for (item_p = JERRY_CONTEXT (context_data_p); item_p != NULL; item_p = item_p->next_p) + { + if (item_p->manager_p == manager_p) + { + return (manager_p->bytes_needed > 0) ? JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p) : NULL; + } + } + + item_p = (jerry_context_data_header_t *) jmem_heap_alloc_block (sizeof (jerry_context_data_header_t) + manager_p->bytes_needed); + item_p->manager_p = manager_p; + item_p->next_p = JERRY_CONTEXT (context_data_p); + JERRY_CONTEXT (context_data_p) = item_p; + + if (manager_p->bytes_needed > 0) + { + ret = JERRY_CONTEXT_DATA_HEADER_USER_DATA (item_p); + memset (ret, 0, manager_p->bytes_needed); + } + + if (manager_p->init_cb) + { + manager_p->init_cb (ret); + } + + return ret; +} /* jerry_context_data */ + +/** + * Register external magic string array + */ +void +jerry_register_magic_strings (const jerry_char_t *const *ext_strings_p, /**< character arrays, representing + * external magic strings' contents */ + uint32_t count, /**< number of the strings */ + const jerry_length_t *str_lengths_p) /**< lengths of all strings */ +{ + lit_magic_strings_ex_set ((const lit_utf8_byte_t *const *) ext_strings_p, + count, + (const lit_utf8_size_t *) str_lengths_p); +} /* jerry_register_magic_strings */ + +/** + * Run garbage collection + */ +void +jerry_heap_gc (jerry_gc_mode_t mode) /**< operational mode */ +{ + if (mode == JERRY_GC_PRESSURE_LOW) + { + /* Call GC directly, because 'ecma_free_unused_memory' might decide it's not yet worth it. */ + ecma_gc_run (); + return; + } + + ecma_free_unused_memory (JMEM_PRESSURE_HIGH); +} /* jerry_heap_gc */ + +/** + * Get heap memory stats. + * + * @return true - get the heap stats successful + * false - otherwise. Usually it is because the MEM_STATS feature is not enabled. + */ +bool +jerry_heap_stats (jerry_heap_stats_t *out_stats_p) /**< [out] heap memory stats */ +{ + JERRY_UNUSED (out_stats_p); + return false; +} /* jerry_heap_stats */ + +#if JERRY_PARSER +/** + * Common code for parsing a script, module, or function. + * + * @return function object value - if script was parsed successfully, + * thrown error - otherwise + */ +static jerry_value_t +jerry_parse_common (void *source_p, /**< script source */ + const jerry_parse_options_t *options_p, /**< parsing options, can be NULL if not used */ + uint32_t parse_opts) /**< internal parsing options */ +{ + if (options_p != NULL) + { + const uint32_t allowed_options = + (JERRY_PARSE_STRICT_MODE | JERRY_PARSE_MODULE | JERRY_PARSE_HAS_ARGUMENT_LIST | JERRY_PARSE_HAS_SOURCE_NAME + | JERRY_PARSE_HAS_START | JERRY_PARSE_HAS_USER_VALUE); + uint32_t options = options_p->options; + + if ((options & ~allowed_options) != 0 + || ((options_p->options & JERRY_PARSE_HAS_ARGUMENT_LIST) + && ((options_p->options & JERRY_PARSE_MODULE) || !ecma_is_value_string (options_p->argument_list))) + || ((options_p->options & JERRY_PARSE_HAS_SOURCE_NAME) && !ecma_is_value_string (options_p->source_name))) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + } + + if (options_p != NULL) + { + parse_opts |= options_p->options & (JERRY_PARSE_STRICT_MODE | JERRY_PARSE_MODULE); + } + + if ((parse_opts & JERRY_PARSE_MODULE) != 0) + { +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_current_p) = ecma_module_create (); +#else /* !JERRY_MODULE_SYSTEM */ + return jerry_throw_sz (JERRY_ERROR_SYNTAX, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ + } + + ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = parser_parse_script (source_p, parse_opts, options_p); + + if (JERRY_UNLIKELY (bytecode_data_p == NULL)) + { +#if JERRY_MODULE_SYSTEM + if ((parse_opts & JERRY_PARSE_MODULE) != 0) + { + ecma_module_cleanup_context (); + } +#endif /* JERRY_MODULE_SYSTEM */ + + return ecma_create_exception_from_context (); + } + +#if JERRY_MODULE_SYSTEM + if (JERRY_UNLIKELY (parse_opts & JERRY_PARSE_MODULE)) + { + ecma_module_t *module_p = JERRY_CONTEXT (module_current_p); + module_p->u.compiled_code_p = bytecode_data_p; + + JERRY_CONTEXT (module_current_p) = NULL; + + return ecma_make_object_value ((ecma_object_t *) module_p); + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (options_p != NULL && (options_p->options & JERRY_PARSE_HAS_ARGUMENT_LIST))) + { + ecma_object_t *global_object_p = ecma_builtin_get_global (); + +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (global_object_p == (ecma_object_t *) ecma_op_function_get_realm (bytecode_data_p)); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p); + ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p); + ecma_bytecode_deref (bytecode_data_p); + + return ecma_make_object_value (func_obj_p); + } + + ecma_object_t *object_p = ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_SCRIPT; + ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.cls.u3.value, bytecode_data_p); + + return ecma_make_object_value (object_p); +} /* jerry_parse_common */ + +#endif /* JERRY_PARSER */ + +/** + * Parse a script, module, or function and create a compiled code using a character string + * + * @return function object value - if script was parsed successfully, + * thrown error - otherwise + */ +jerry_value_t +jerry_parse (const jerry_char_t *source_p, /**< script source */ + size_t source_size, /**< script source size */ + const jerry_parse_options_t *options_p) /**< parsing options, can be NULL if not used */ +{ +#if JERRY_PARSER + parser_source_char_t source_char; + source_char.source_p = source_p; + source_char.source_size = source_size; + + return jerry_parse_common ((void *) &source_char, options_p, JERRY_PARSE_NO_OPTS); +#else /* !JERRY_PARSER */ + JERRY_UNUSED (source_p); + JERRY_UNUSED (source_size); + JERRY_UNUSED (options_p); + + return jerry_throw_sz (JERRY_ERROR_SYNTAX, ecma_get_error_msg (ECMA_ERR_PARSER_NOT_SUPPORTED)); +#endif /* JERRY_PARSER */ +} /* jerry_parse */ + +/** + * Parse a script, module, or function and create a compiled code using a string value + * + * @return function object value - if script was parsed successfully, + * thrown error - otherwise + */ +jerry_value_t +jerry_parse_value (const jerry_value_t source, /**< script source */ + const jerry_parse_options_t *options_p) /**< parsing options, can be NULL if not used */ +{ +#if JERRY_PARSER + if (!ecma_is_value_string (source)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return jerry_parse_common ((void *) &source, options_p, ECMA_PARSE_HAS_SOURCE_VALUE); +#else /* !JERRY_PARSER */ + JERRY_UNUSED (source); + JERRY_UNUSED (options_p); + + return jerry_throw_sz (JERRY_ERROR_SYNTAX, ecma_get_error_msg (ECMA_ERR_PARSER_NOT_SUPPORTED)); +#endif /* JERRY_PARSER */ +} /* jerry_parse_value */ + +/** + * Run a Script or Module created by jerry_parse. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return result of bytecode - if run was successful + * thrown error - otherwise + */ +jerry_value_t +jerry_run (const jerry_value_t script) /**< script or module to run */ +{ + if (!ecma_is_value_object (script)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *object_p = ecma_get_object_from_value (script); + + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SCRIPT)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_SCRIPT); + + return jerry_return (vm_run_global (bytecode_data_p, object_p)); +} /* jerry_run */ + +/** + * Perform eval + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return result of eval, may be error value. + */ +jerry_value_t +jerry_eval (const jerry_char_t *source_p, /**< source code */ + size_t source_size, /**< length of source code */ + uint32_t flags) /**< jerry_parse_opts_t flags */ +{ + uint32_t allowed_parse_options = JERRY_PARSE_STRICT_MODE; + + if ((flags & ~allowed_parse_options) != 0) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + parser_source_char_t source_char; + source_char.source_p = source_p; + source_char.source_size = source_size; + + return jerry_return (ecma_op_eval_chars_buffer ((void *) &source_char, flags)); +} /* jerry_eval */ + +/** + * Link modules to their dependencies. The dependencies are resolved by a user callback. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true - if linking is successful, error - otherwise + */ +jerry_value_t +jerry_module_link (const jerry_value_t module, /**< root module */ + jerry_module_resolve_cb_t callback, /**< resolve module callback, uses + * jerry_module_resolve when NULL is passed */ + void *user_p) /**< pointer passed to the resolve callback */ +{ +#if JERRY_MODULE_SYSTEM + if (callback == NULL) + { + callback = jerry_module_resolve; + } + + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + return jerry_return (ecma_module_link (module_p, callback, user_p)); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_link */ + +/** + * Evaluate a module and its dependencies. The module must be in linked state. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return result of module bytecode execution - if evaluation was successful + * error - otherwise + */ +jerry_value_t +jerry_module_evaluate (const jerry_value_t module) /**< root module */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_LINKED) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_MUST_BE_IN_LINKED_STATE)); + } + + return jerry_return (ecma_module_evaluate (module_p)); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_evaluate */ + +/** + * Returns the current status of a module + * + * @return current status - if module is a module, + * JERRY_MODULE_STATE_INVALID - otherwise + */ +jerry_module_state_t +jerry_module_state (const jerry_value_t module) /**< module object */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return JERRY_MODULE_STATE_INVALID; + } + + return (jerry_module_state_t) module_p->header.u.cls.u1.module_state; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return JERRY_MODULE_STATE_INVALID; +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_state */ + +/** + * Sets a callback which is called after a module state is changed to linked, evaluated, or error. + */ +void +jerry_module_on_state_changed (jerry_module_state_changed_cb_t callback, /**< callback */ + void *user_p) /**< pointer passed to the callback */ +{ +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_state_changed_callback_p) = callback; + JERRY_CONTEXT (module_state_changed_callback_user_p) = user_p; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_on_state_changed */ + +/** + * Sets a callback which is called when an import.meta expression of a module is evaluated the first time. + */ +void +jerry_module_on_import_meta (jerry_module_import_meta_cb_t callback, /**< callback */ + void *user_p) /**< pointer passed to the callback */ +{ +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_import_meta_callback_p) = callback; + JERRY_CONTEXT (module_import_meta_callback_user_p) = user_p; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_on_import_meta */ + +/** + * Returns the number of import/export requests of a module + * + * @return number of import/export requests of a module + */ +size_t +jerry_module_request_count (const jerry_value_t module) /**< module */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return 0; + } + + size_t number_of_requests = 0; + + ecma_module_node_t *node_p = module_p->imports_p; + + while (node_p != NULL) + { + number_of_requests++; + node_p = node_p->next_p; + } + + return number_of_requests; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return 0; +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_request_count */ + +/** + * Returns the module request specified by the request_index argument + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return string - if the request has not been resolved yet, + * module object - if the request has been resolved successfully, + * error - otherwise + */ +jerry_value_t +jerry_module_request (const jerry_value_t module, /**< module */ + size_t request_index) /**< request index */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + ecma_module_node_t *node_p = module_p->imports_p; + + while (node_p != NULL) + { + if (request_index == 0) + { + return ecma_copy_value (node_p->u.path_or_module); + } + + --request_index; + node_p = node_p->next_p; + } + + return jerry_throw_sz (JERRY_ERROR_RANGE, ecma_get_error_msg (ECMA_ERR_REQUEST_IS_NOT_AVAILABLE)); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + JERRY_UNUSED (request_index); + + return jerry_throw_sz (JERRY_ERROR_RANGE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_request */ + +/** + * Returns the namespace object of a module + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return object - if namespace object is available, + * error - otherwise + */ +jerry_value_t +jerry_module_namespace (const jerry_value_t module) /**< module */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (module_p->header.u.cls.u1.module_state < JERRY_MODULE_STATE_LINKED + || module_p->header.u.cls.u1.module_state > JERRY_MODULE_STATE_EVALUATED) + { + return jerry_throw_sz (JERRY_ERROR_RANGE, ecma_get_error_msg (ECMA_ERR_NAMESPACE_OBJECT_IS_NOT_AVAILABLE)); + } + + JERRY_ASSERT (module_p->namespace_object_p != NULL); + + ecma_ref_object (module_p->namespace_object_p); + return ecma_make_object_value (module_p->namespace_object_p); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (module); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_namespace */ + +/** + * Sets the callback which is called when dynamic imports are resolved + */ +void +jerry_module_on_import (jerry_module_import_cb_t callback_p, /**< callback which handles + * dynamic import calls */ + void *user_p) /**< user pointer passed to the callback */ +{ +#if JERRY_MODULE_SYSTEM + JERRY_CONTEXT (module_import_callback_p) = callback_p; + JERRY_CONTEXT (module_import_callback_user_p) = user_p; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback_p); + JERRY_UNUSED (user_p); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_module_on_import */ + +/** + * Creates a native module with a list of exports. The initial state of the module is linked. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return native module - if the module is successfully created, + * error - otherwise + */ +jerry_value_t +jerry_native_module (jerry_native_module_evaluate_cb_t callback, /**< evaluation callback for + * native modules */ + const jerry_value_t *const exports_p, /**< list of the exported bindings of the module, + * must be valid string identifiers */ + size_t export_count) /**< number of exports in the exports_p list */ +{ +#if JERRY_MODULE_SYSTEM + ecma_object_t *global_object_p = ecma_builtin_get_global (); + ecma_object_t *scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p)); + ecma_module_names_t *local_exports_p = NULL; + + for (size_t i = 0; i < export_count; i++) + { + if (!ecma_is_value_string (exports_p[i])) + { + ecma_deref_object (scope_p); + ecma_module_release_module_names (local_exports_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_EXPORTS_MUST_BE_STRING_VALUES)); + } + + ecma_string_t *name_str_p = ecma_get_string_from_value (exports_p[i]); + + bool valid_identifier = false; + + ECMA_STRING_TO_UTF8_STRING (name_str_p, name_start_p, name_size); + + if (name_size > 0) + { + const lit_utf8_byte_t *name_p = name_start_p; + const lit_utf8_byte_t *name_end_p = name_start_p + name_size; + lit_code_point_t code_point; + + lit_utf8_size_t size = lit_read_code_point_from_cesu8 (name_p, name_end_p, &code_point); + + if (lit_code_point_is_identifier_start (code_point)) + { + name_p += size; + + valid_identifier = true; + + while (name_p < name_end_p) + { + size = lit_read_code_point_from_cesu8 (name_p, name_end_p, &code_point); + + if (!lit_code_point_is_identifier_part (code_point)) + { + valid_identifier = false; + break; + } + + name_p += size; + } + } + } + + ECMA_FINALIZE_UTF8_STRING (name_start_p, name_size); + + if (!valid_identifier) + { + ecma_deref_object (scope_p); + ecma_module_release_module_names (local_exports_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_EXPORTS_MUST_BE_VALID_IDENTIFIERS)); + } + + if (ecma_find_named_property (scope_p, name_str_p) != NULL) + { + continue; + } + + ecma_create_named_data_property (scope_p, name_str_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + ecma_module_names_t *new_export_p; + new_export_p = (ecma_module_names_t *) jmem_heap_alloc_block (sizeof (ecma_module_names_t)); + + new_export_p->next_p = local_exports_p; + local_exports_p = new_export_p; + + ecma_ref_ecma_string (name_str_p); + new_export_p->imex_name_p = name_str_p; + + ecma_ref_ecma_string (name_str_p); + new_export_p->local_name_p = name_str_p; + } + + ecma_module_t *module_p = ecma_module_create (); + + module_p->header.u.cls.u2.module_flags |= ECMA_MODULE_IS_NATIVE; + module_p->scope_p = scope_p; + module_p->local_exports_p = local_exports_p; + module_p->u.callback = callback; + + ecma_deref_object (scope_p); + + return ecma_make_object_value (&module_p->header.object); + +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (callback); + JERRY_UNUSED (exports_p); + JERRY_UNUSED (export_count); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_native_module */ + +/** + * Gets the value of an export which belongs to a native module. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the export - if success + * error - otherwise + */ +jerry_value_t +jerry_native_module_get (const jerry_value_t native_module, /**< a native module object */ + const jerry_value_t export_name) /**< string identifier of the export */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (native_module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) || !ecma_is_value_string (export_name)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_property_t *property_p = ecma_find_named_property (module_p->scope_p, ecma_get_string_from_value (export_name)); + + if (property_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_UNKNOWN_EXPORT)); + } + + return ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (native_module); + JERRY_UNUSED (export_name); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_native_module_get */ + +/** + * Sets the value of an export which belongs to a native module. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * error - otherwise + */ +jerry_value_t +jerry_native_module_set (jerry_value_t native_module, /**< a native module object */ + const jerry_value_t export_name, /**< string identifier of the export */ + const jerry_value_t value) /**< new value of the export */ +{ +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_p = ecma_module_get_resolved_module (native_module); + + if (module_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_NOT_MODULE)); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) || !ecma_is_value_string (export_name) + || ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_property_t *property_p = ecma_find_named_property (module_p->scope_p, ecma_get_string_from_value (export_name)); + + if (property_p == NULL) + { + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_UNKNOWN_EXPORT)); + } + + ecma_named_data_property_assign_value (module_p->scope_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + return ECMA_VALUE_TRUE; +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_UNUSED (native_module); + JERRY_UNUSED (export_name); + JERRY_UNUSED (value); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_MODULE_NOT_SUPPORTED)); +#endif /* JERRY_MODULE_SYSTEM */ +} /* jerry_native_module_set */ + +/** + * Run enqueued microtasks created by Promise or AsyncFunction objects. + * Tasks are executed until an exception is thrown or all tasks are executed. + * + * Note: returned value must be freed with jerry_value_free + * + * @return result of last executed job, possibly an exception. + */ +jerry_value_t +jerry_run_jobs (void) +{ + return jerry_return (ecma_process_all_enqueued_jobs ()); +} /* jerry_run_jobs */ + +/** + * Get global object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return api value of global object + */ +jerry_value_t +jerry_current_realm (void) +{ + ecma_object_t *global_obj_p = ecma_builtin_get_global (); + ecma_ref_object (global_obj_p); + return ecma_make_object_value (global_obj_p); +} /* jerry_current_realm */ + +/** + * Check if the specified value is an abort value. + * + * @return true - if both the error and abort values are set, + * false - otherwise + */ +bool +jerry_value_is_abort (const jerry_value_t value) /**< api value */ +{ + if (!ecma_is_value_exception (value)) + { + return false; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + return (error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_ABORT) != 0; +} /* jerry_value_is_abort */ + +/** + * Check if the specified value is an array object value. + * + * @return true - if the specified value is an array object, + * false - otherwise + */ +bool +jerry_value_is_array (const jerry_value_t value) /**< jerry api value */ +{ + return (ecma_is_value_object (value) + && ecma_get_object_base_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_BASE_TYPE_ARRAY); +} /* jerry_value_is_array */ + +/** + * Check if the specified value is boolean. + * + * @return true - if the specified value is boolean, + * false - otherwise + */ +bool +jerry_value_is_boolean (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_boolean (value); +} /* jerry_value_is_boolean */ + +/** + * Check if the specified value is true. + * + * @return true - if the specified value is true + * false - otherwise + */ +bool +jerry_value_is_true (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_true (value); +} /* jerry_value_is_true */ + +/** + * Check if the specified value is false. + * + * @return true - if the specified value is false + * false - otherwise + */ +bool +jerry_value_is_false (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_false (value); +} /* jerry_value_is_false */ + +/** + * Check if the specified value is a constructor function object value. + * + * @return true - if the specified value is a function value that implements [[Construct]], + * false - otherwise + */ +bool +jerry_value_is_constructor (const jerry_value_t value) /**< jerry api value */ +{ + return ecma_is_constructor (value); +} /* jerry_value_is_constructor */ + +/** + * Check if the specified value is an error or abort value. + * + * @return true - if the specified value is an error value, + * false - otherwise + */ +bool +jerry_value_is_exception (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_exception (value); +} /* jerry_value_is_exception */ + +/** + * Check if the specified value is a function object value. + * + * @return true - if the specified value is callable, + * false - otherwise + */ +bool +jerry_value_is_function (const jerry_value_t value) /**< api value */ +{ + return ecma_op_is_callable (value); +} /* jerry_value_is_function */ + +/** + * Check if the specified value is an async function object value. + * + * @return true - if the specified value is an async function, + * false - otherwise + */ +bool +jerry_value_is_async_function (const jerry_value_t value) /**< api value */ +{ + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) obj_p); + uint16_t type = CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags); + + return (type == CBC_FUNCTION_ASYNC || type == CBC_FUNCTION_ASYNC_ARROW || type == CBC_FUNCTION_ASYNC_GENERATOR); + } + } + + return false; +} /* jerry_value_is_async_function */ + +/** + * Check if the specified value is number. + * + * @return true - if the specified value is number, + * false - otherwise + */ +bool +jerry_value_is_number (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_number (value); +} /* jerry_value_is_number */ + +/** + * Check if the specified value is null. + * + * @return true - if the specified value is null, + * false - otherwise + */ +bool +jerry_value_is_null (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_null (value); +} /* jerry_value_is_null */ + +/** + * Check if the specified value is object. + * + * @return true - if the specified value is object, + * false - otherwise + */ +bool +jerry_value_is_object (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_object (value); +} /* jerry_value_is_object */ + +/** + * Check if the specified value is promise. + * + * @return true - if the specified value is promise, + * false - otherwise + */ +bool +jerry_value_is_promise (const jerry_value_t value) /**< api value */ +{ + return (ecma_is_value_object (value) && ecma_is_promise (ecma_get_object_from_value (value))); +} /* jerry_value_is_promise */ + +/** + * Check if the specified value is a proxy object. + * + * @return true - if the specified value is a proxy object, + * false - otherwise + */ +bool +jerry_value_is_proxy (const jerry_value_t value) /**< api value */ +{ +#if JERRY_BUILTIN_PROXY + return (ecma_is_value_object (value) && ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (value))); +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_PROXY */ +} /* jerry_value_is_proxy */ + +/** + * Check if the specified value is string. + * + * @return true - if the specified value is string, + * false - otherwise + */ +bool +jerry_value_is_string (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_string (value); +} /* jerry_value_is_string */ + +/** + * Check if the specified value is symbol. + * + * @return true - if the specified value is symbol, + * false - otherwise + */ +bool +jerry_value_is_symbol (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_symbol (value); +} /* jerry_value_is_symbol */ + +/** + * Check if the specified value is BigInt. + * + * @return true - if the specified value is BigInt, + * false - otherwise + */ +bool +jerry_value_is_bigint (const jerry_value_t value) /**< api value */ +{ +#if JERRY_BUILTIN_BIGINT + return ecma_is_value_bigint (value); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_value_is_bigint */ + +/** + * Check if the specified value is undefined. + * + * @return true - if the specified value is undefined, + * false - otherwise + */ +bool +jerry_value_is_undefined (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_undefined (value); +} /* jerry_value_is_undefined */ + +/** + * Perform the base type of the JavaScript value. + * + * @return jerry_type_t value + */ +jerry_type_t +jerry_value_type (const jerry_value_t value) /**< input value to check */ +{ + if (ecma_is_value_exception (value)) + { + return JERRY_TYPE_EXCEPTION; + } + + lit_magic_string_id_t lit_id = ecma_get_typeof_lit_id (value); + + JERRY_ASSERT (lit_id != LIT_MAGIC_STRING__EMPTY); + + switch (lit_id) + { + case LIT_MAGIC_STRING_UNDEFINED: + { + return JERRY_TYPE_UNDEFINED; + } + case LIT_MAGIC_STRING_BOOLEAN: + { + return JERRY_TYPE_BOOLEAN; + } + case LIT_MAGIC_STRING_NUMBER: + { + return JERRY_TYPE_NUMBER; + } + case LIT_MAGIC_STRING_STRING: + { + return JERRY_TYPE_STRING; + } + case LIT_MAGIC_STRING_SYMBOL: + { + return JERRY_TYPE_SYMBOL; + } + case LIT_MAGIC_STRING_FUNCTION: + { + return JERRY_TYPE_FUNCTION; + } +#if JERRY_BUILTIN_BIGINT + case LIT_MAGIC_STRING_BIGINT: + { + return JERRY_TYPE_BIGINT; + } +#endif /* JERRY_BUILTIN_BIGINT */ + default: + { + JERRY_ASSERT (lit_id == LIT_MAGIC_STRING_OBJECT); + + /* Based on the ECMA 262 5.1 standard the 'null' value is an object. + * Thus we'll do an extra check for 'null' here. + */ + return ecma_is_value_null (value) ? JERRY_TYPE_NULL : JERRY_TYPE_OBJECT; + } + } +} /* jerry_value_type */ + +/** + * Used by jerry_object_type to get the type of class objects + */ +static const uint8_t jerry_class_object_type[] = { + /* These objects require custom property resolving. */ + JERRY_OBJECT_TYPE_STRING, /**< type of ECMA_OBJECT_CLASS_STRING */ + JERRY_OBJECT_TYPE_ARGUMENTS, /**< type of ECMA_OBJECT_CLASS_ARGUMENTS */ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_OBJECT_TYPE_TYPEDARRAY, /**< type of ECMA_OBJECT_CLASS_TYPEDARRAY */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + JERRY_OBJECT_TYPE_MODULE_NAMESPACE, /**< type of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* These objects are marked by Garbage Collector. */ + JERRY_OBJECT_TYPE_GENERATOR, /**< type of ECMA_OBJECT_CLASS_GENERATOR */ + JERRY_OBJECT_TYPE_GENERATOR, /**< type of ECMA_OBJECT_CLASS_ASYNC_GENERATOR */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_ARRAY_ITERATOR */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_SET_ITERATOR */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_MAP_ITERATOR */ +#if JERRY_BUILTIN_REGEXP + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM + JERRY_OBJECT_TYPE_MODULE, /**< type of ECMA_OBJECT_CLASS_MODULE */ +#endif /* JERRY_MODULE_SYSTEM */ + JERRY_OBJECT_TYPE_PROMISE, /**< type of ECMA_OBJECT_CLASS_PROMISE */ + JERRY_OBJECT_TYPE_GENERIC, /**< type of ECMA_OBJECT_CLASS_PROMISE_CAPABILITY */ + JERRY_OBJECT_TYPE_GENERIC, /**< type of ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR */ +#if JERRY_BUILTIN_DATAVIEW + JERRY_OBJECT_TYPE_DATAVIEW, /**< type of ECMA_OBJECT_CLASS_DATAVIEW */ +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + JERRY_OBJECT_TYPE_CONTAINER, /**< type of ECMA_OBJECT_CLASS_CONTAINER */ +#endif /* JERRY_BUILTIN_CONTAINER */ + + /* Normal objects. */ + JERRY_OBJECT_TYPE_BOOLEAN, /**< type of ECMA_OBJECT_CLASS_BOOLEAN */ + JERRY_OBJECT_TYPE_NUMBER, /**< type of ECMA_OBJECT_CLASS_NUMBER */ + JERRY_OBJECT_TYPE_ERROR, /**< type of ECMA_OBJECT_CLASS_ERROR */ + JERRY_OBJECT_TYPE_GENERIC, /**< type of ECMA_OBJECT_CLASS_INTERNAL_OBJECT */ +#if JERRY_PARSER + JERRY_OBJECT_TYPE_SCRIPT, /**< type of ECMA_OBJECT_CLASS_SCRIPT */ +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + JERRY_OBJECT_TYPE_DATE, /**< type of ECMA_OBJECT_CLASS_DATE */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + JERRY_OBJECT_TYPE_REGEXP, /**< type of ECMA_OBJECT_CLASS_REGEXP */ +#endif /* JERRY_BUILTIN_REGEXP */ + JERRY_OBJECT_TYPE_SYMBOL, /**< type of ECMA_OBJECT_CLASS_SYMBOL */ + JERRY_OBJECT_TYPE_ITERATOR, /**< type of ECMA_OBJECT_CLASS_STRING_ITERATOR */ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_OBJECT_TYPE_ARRAYBUFFER, /**< type of ECMA_OBJECT_CLASS_ARRAY_BUFFER */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + JERRY_OBJECT_TYPE_SHARED_ARRAY_BUFFER, /**< type of ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER */ +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT + JERRY_OBJECT_TYPE_BIGINT, /**< type of ECMA_OBJECT_CLASS_BIGINT */ +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_WEAKREF + JERRY_OBJECT_TYPE_WEAKREF, /**< type of ECMA_OBJECT_CLASS_WEAKREF */ +#endif /* JERRY_BUILTIN_WEAKREF */ +}; + +JERRY_STATIC_ASSERT ((sizeof (jerry_class_object_type) == ECMA_OBJECT_CLASS__MAX), + jerry_class_object_type_must_have_object_class_max_elements); + +/** + * Get the object type of the given value + * + * @return JERRY_OBJECT_TYPE_NONE - if the given value is not an object + * jerry_object_type_t value - otherwise + */ +jerry_object_type_t +jerry_object_type (const jerry_value_t value) /**< input value to check */ +{ + if (!ecma_is_value_object (value)) + { + return JERRY_OBJECT_TYPE_NONE; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (value); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + switch (ecma_get_object_type (obj_p)) + { + case ECMA_OBJECT_TYPE_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { + JERRY_ASSERT (ext_obj_p->u.cls.type < ECMA_OBJECT_CLASS__MAX); + return (jerry_object_type_t) jerry_class_object_type[ext_obj_p->u.cls.type]; + } + case ECMA_OBJECT_TYPE_ARRAY: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + return JERRY_OBJECT_TYPE_ARRAY; + } + case ECMA_OBJECT_TYPE_PROXY: + { + return JERRY_OBJECT_TYPE_PROXY; + } + case ECMA_OBJECT_TYPE_FUNCTION: + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + return JERRY_OBJECT_TYPE_FUNCTION; + } + default: + { + break; + } + } + + return JERRY_OBJECT_TYPE_GENERIC; +} /* jerry_object_type */ + +/** + * Get the function type of the given value + * + * @return JERRY_FUNCTION_TYPE_NONE - if the given value is not a function object + * jerry_function_type_t value - otherwise + */ +jerry_function_type_t +jerry_function_type (const jerry_value_t value) /**< input value to check */ +{ + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + switch (ecma_get_object_type (obj_p)) + { + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + return JERRY_FUNCTION_TYPE_BOUND; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + return JERRY_FUNCTION_TYPE_GENERIC; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_obj_p); + + switch (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags)) + { + case CBC_FUNCTION_ARROW: + case CBC_FUNCTION_ASYNC_ARROW: + { + return JERRY_FUNCTION_TYPE_ARROW; + } + case CBC_FUNCTION_GENERATOR: + case CBC_FUNCTION_ASYNC_GENERATOR: + { + return JERRY_FUNCTION_TYPE_GENERATOR; + } + case CBC_FUNCTION_ACCESSOR: + { + return JERRY_FUNCTION_TYPE_ACCESSOR; + } + default: + { + break; + } + } + return JERRY_FUNCTION_TYPE_GENERIC; + } + default: + { + break; + } + } + } + + return JERRY_FUNCTION_TYPE_NONE; +} /* jerry_function_type */ + +/** + * Get the itearator type of the given value + * + * @return JERRY_ITERATOR_TYPE_NONE - if the given value is not an iterator object + * jerry_iterator_type_t value - otherwise + */ +jerry_iterator_type_t +jerry_iterator_type (const jerry_value_t value) /**< input value to check */ +{ + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS) + { + switch (ext_obj_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARRAY_ITERATOR: + { + return JERRY_ITERATOR_TYPE_ARRAY; + } +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_SET_ITERATOR: + { + return JERRY_ITERATOR_TYPE_SET; + } + case ECMA_OBJECT_CLASS_MAP_ITERATOR: + { + return JERRY_ITERATOR_TYPE_MAP; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + case ECMA_OBJECT_CLASS_STRING_ITERATOR: + { + return JERRY_ITERATOR_TYPE_STRING; + } + default: + { + break; + } + } + } + } + + return JERRY_ITERATOR_TYPE_NONE; +} /* jerry_iterator_type */ + +/** + * Check if the specified feature is enabled. + * + * @return true - if the specified feature is enabled, + * false - otherwise + */ +bool +jerry_feature_enabled (const jerry_feature_t feature) /**< feature to check */ +{ + JERRY_ASSERT (feature < JERRY_FEATURE__COUNT); + + return (false +#if JERRY_CPOINTER_32_BIT + || feature == JERRY_FEATURE_CPOINTER_32_BIT +#endif /* JERRY_CPOINTER_32_BIT */ +#if JERRY_ERROR_MESSAGES + || feature == JERRY_FEATURE_ERROR_MESSAGES +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_PARSER + || feature == JERRY_FEATURE_JS_PARSER +#endif /* JERRY_PARSER */ +#if JERRY_PARSER_DUMP_BYTE_CODE + || feature == JERRY_FEATURE_PARSER_DUMP +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ +#if JERRY_REGEXP_DUMP_BYTE_CODE + || feature == JERRY_FEATURE_REGEXP_DUMP +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ +#if JERRY_SNAPSHOT_SAVE + || feature == JERRY_FEATURE_SNAPSHOT_SAVE +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_SNAPSHOT_EXEC + || feature == JERRY_FEATURE_SNAPSHOT_EXEC +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_VM_HALT + || feature == JERRY_FEATURE_VM_EXEC_STOP +#endif /* JERRY_VM_HALT */ +#if JERRY_VM_THROW + || feature == JERRY_FEATURE_VM_THROW +#endif /* JERRY_VM_THROW */ +#if JERRY_BUILTIN_TYPEDARRAY + || feature == JERRY_FEATURE_TYPEDARRAY +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATAVIEW + || feature == JERRY_FEATURE_DATAVIEW +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_PROXY + || feature == JERRY_FEATURE_PROXY +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_DATE + || feature == JERRY_FEATURE_DATE +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + || feature == JERRY_FEATURE_REGEXP +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_LINE_INFO + || feature == JERRY_FEATURE_LINE_INFO +#endif /* JERRY_LINE_INFO */ +#if JERRY_LOGGING + || feature == JERRY_FEATURE_LOGGING +#endif /* JERRY_LOGGING */ +#if JERRY_BUILTIN_GLOBAL_THIS + || feature == JERRY_FEATURE_GLOBAL_THIS +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ +#if JERRY_BUILTIN_CONTAINER + || feature == JERRY_FEATURE_MAP || feature == JERRY_FEATURE_SET || feature == JERRY_FEATURE_WEAKMAP + || feature == JERRY_FEATURE_WEAKSET +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_WEAKREF + || feature == JERRY_FEATURE_WEAKREF +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_BIGINT + || feature == JERRY_FEATURE_BIGINT +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_REALMS + || feature == JERRY_FEATURE_REALM +#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_MODULE_SYSTEM + || feature == JERRY_FEATURE_MODULE +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_FUNCTION_TO_STRING + || feature == JERRY_FEATURE_FUNCTION_TO_STRING +#endif /* JERRY_FUNCTION_TO_STRING */ + ); +} /* jerry_feature_enabled */ + +/** + * Perform binary operation on the given operands (==, ===, <, >, etc.). + * + * @return error - if argument has an error flag or operation is unsuccessful or unsupported + * true/false - the result of the binary operation on the given operands otherwise + */ +jerry_value_t +jerry_binary_op (jerry_binary_op_t operation, /**< operation */ + const jerry_value_t lhs, /**< first operand */ + const jerry_value_t rhs) /**< second operand */ +{ + if (ecma_is_value_exception (lhs) || ecma_is_value_exception (rhs)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + switch (operation) + { + case JERRY_BIN_OP_EQUAL: + { + return jerry_return (ecma_op_abstract_equality_compare (lhs, rhs)); + } + case JERRY_BIN_OP_STRICT_EQUAL: + { + return ecma_make_boolean_value (ecma_op_strict_equality_compare (lhs, rhs)); + } + case JERRY_BIN_OP_LESS: + { + return jerry_return (opfunc_relation (lhs, rhs, true, false)); + } + case JERRY_BIN_OP_LESS_EQUAL: + { + return jerry_return (opfunc_relation (lhs, rhs, false, true)); + } + case JERRY_BIN_OP_GREATER: + { + return jerry_return (opfunc_relation (lhs, rhs, false, false)); + } + case JERRY_BIN_OP_GREATER_EQUAL: + { + return jerry_return (opfunc_relation (lhs, rhs, true, true)); + } + case JERRY_BIN_OP_INSTANCEOF: + { + if (!ecma_is_value_object (lhs) || !ecma_op_is_callable (rhs)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *proto_obj_p = ecma_get_object_from_value (rhs); + return jerry_return (ecma_op_object_has_instance (proto_obj_p, lhs)); + } + case JERRY_BIN_OP_ADD: + { + return jerry_return (opfunc_addition (lhs, rhs)); + } + case JERRY_BIN_OP_SUB: + case JERRY_BIN_OP_MUL: + case JERRY_BIN_OP_DIV: + case JERRY_BIN_OP_REM: + { + return jerry_return (do_number_arithmetic ((number_arithmetic_op) ((int) operation - ECMA_NUMBER_ARITHMETIC_OP_API_OFFSET), lhs, rhs)); + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_UNSUPPORTED_BINARY_OPERATION)); + } + } +} /* jerry_binary_op */ + +/** + * Create an abort value containing the argument value. If the second argument is true + * the function will take ownership ofthe input value, otherwise the value will be copied. + * + * @return api abort value + */ +jerry_value_t +jerry_throw_abort (jerry_value_t value, /**< api value */ + bool take_ownership) /**< release api value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + /* This is a rare case so it is optimized for + * binary size rather than performance. */ + if (jerry_value_is_abort (value)) + { + return take_ownership ? value : jerry_value_copy (value); + } + + value = jerry_exception_value (value, take_ownership); + take_ownership = true; + } + + if (!take_ownership) + { + value = ecma_copy_value (value); + } + + return ecma_create_exception (value, ECMA_ERROR_API_FLAG_ABORT); +} /* jerry_throw_abort */ + +/** + * Create an exception value containing the argument value. If the second argument is true + * the function will take ownership ofthe input value, otherwise the value will be copied. + * + * @return exception value + */ +jerry_value_t +jerry_throw_value (jerry_value_t value, /**< value */ + bool take_ownership) /**< take ownership of the value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + /* This is a rare case so it is optimized for + * binary size rather than performance. */ + if (!jerry_value_is_abort (value)) + { + return take_ownership ? value : jerry_value_copy (value); + } + + value = jerry_exception_value (value, take_ownership); + take_ownership = true; + } + + if (!take_ownership) + { + value = ecma_copy_value (value); + } + + return ecma_create_exception (value, ECMA_ERROR_API_FLAG_NONE); +} /* jerry_throw_value */ + +/** + * Get the value contained in an exception. If the second argument is true + * it will release the argument exception value in the process. + * + * @return value in exception + */ +jerry_value_t +jerry_exception_value (jerry_value_t value, /**< api value */ + bool free_exception) /**< release api value */ +{ + if (!ecma_is_value_exception (value)) + { + return free_exception ? value : ecma_copy_value (value); + } + + jerry_value_t ret_val = jerry_value_copy (ecma_get_extended_primitive_from_value (value)->u.value); + + if (free_exception) + { + jerry_value_free (value); + } + return ret_val; +} /* jerry_exception_value */ + +/** + * Set new decorator callback for Error objects. The decorator can + * create or update any properties of the newly created Error object. + */ +void +jerry_error_on_created (jerry_error_object_created_cb_t callback, /**< new callback */ + void *user_p) /**< user pointer passed to the callback */ +{ + JERRY_CONTEXT (error_object_created_callback_p) = callback; + JERRY_CONTEXT (error_object_created_callback_user_p) = user_p; +} /* jerry_error_on_created */ + +/** + * When JERRY_VM_THROW is enabled, the callback passed to this + * function is called when an error is thrown in ECMAScript code. + */ +void +jerry_on_throw (jerry_throw_cb_t callback, /**< callback which is called on throws */ + void *user_p) /**< pointer passed to the function */ +{ +#if JERRY_VM_THROW + JERRY_CONTEXT (vm_throw_callback_p) = callback; + JERRY_CONTEXT (vm_throw_callback_user_p) = user_p; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_VM_THROW */ +} /* jerry_on_throw */ + +/** + * Checks whether the callback set by jerry_on_throw captured the error + * + * @return true, if the vm throw callback captured the error + * false, otherwise + */ +bool +jerry_exception_is_captured (const jerry_value_t value) /**< exception value */ +{ +#if JERRY_VM_THROW + if (!ecma_is_value_exception (value)) + { + return false; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + return (error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_THROW_CAPTURED) != 0; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_VM_THROW */ +} /* jerry_exception_is_captured */ + +/** + * Sets whether the callback set by jerry_on_throw should capture the exception or not + */ +void +jerry_exception_allow_capture (jerry_value_t value, /**< exception value */ + bool should_capture) /**< callback should capture this error */ +{ +#if JERRY_VM_THROW + if (!ecma_is_value_exception (value)) + { + return; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + if (should_capture) + { + error_ref_p->refs_and_type &= ~(uint32_t) ECMA_ERROR_API_FLAG_THROW_CAPTURED; + return; + } + + error_ref_p->refs_and_type |= ECMA_ERROR_API_FLAG_THROW_CAPTURED; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (value); + JERRY_UNUSED (should_capture); +#endif /* JERRY_VM_THROW */ +} /* jerry_exception_allow_capture */ + +/** + * Check if the given value is an Error object. + * + * @return true - if it is an Error object + * false - otherwise + */ +bool +jerry_value_is_error (const jerry_value_t value) /**< api value */ +{ + return ecma_is_value_object (value) + && ecma_object_class_is (ecma_get_object_from_value (value), ECMA_OBJECT_CLASS_ERROR); +} /* jerry_value_is_error */ + +/** + * Return the type of the Error object if possible. + * + * @return one of the jerry_error_t value as the type of the Error object + * JERRY_ERROR_NONE - if the input value is not an Error object + */ +jerry_error_t +jerry_error_type (jerry_value_t value) /**< api value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + value = ecma_get_extended_primitive_from_value (value)->u.value; + } + + if (!ecma_is_value_object (value)) + { + return JERRY_ERROR_NONE; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + /* TODO(check if error object) */ + jerry_error_t error_type = ecma_get_error_type (object_p); + + return (jerry_error_t) error_type; +} /* jerry_error_type */ + +/** + * Get number from the specified value as a double. + * + * @return stored number as double + */ +double +jerry_value_as_number (const jerry_value_t value) /**< api value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + return (double) ecma_get_number_from_value (value); +} /* jerry_value_as_number */ + +/** + * Call ToBoolean operation on the api value. + * + * @return true - if the logical value is true + * false - otherwise + */ +bool +jerry_value_to_boolean (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return false; + } + + return ecma_op_to_boolean (value); +} /* jerry_value_to_boolean */ + +/** + * Call ToNumber operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted number value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_number (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + ecma_number_t num; + ecma_value_t ret_value = ecma_op_to_number (value, &num); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_number_value (num); +} /* jerry_value_to_number */ + +/** + * Call ToObject operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted object value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_object (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return jerry_return (ecma_op_to_object (value)); +} /* jerry_value_to_object */ + +/** + * Call ToPrimitive operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted primitive value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_primitive (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return jerry_return (ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NO)); +} /* jerry_value_to_primitive */ + +/** + * Call the ToString ecma builtin operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return converted string value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_string (const jerry_value_t value) /**< input value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + ecma_string_t *str_p = ecma_op_to_string (value); + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_string_value (str_p); +} /* jerry_value_to_string */ + +/** + * Call the BigInt constructor ecma builtin operation on the api value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return BigInt value - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_value_to_bigint (const jerry_value_t value) /**< input value */ +{ +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return jerry_return (ecma_bigint_to_bigint (value, true)); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_BIGINT_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_value_to_bigint */ + +/** + * Convert any number to integer number. + * + * Note: + * For non-number values 0 is returned. + * + * @return integer representation of the number. + */ +double +jerry_value_as_integer (const jerry_value_t value) /**< input value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + double number = ecma_get_number_from_value (value); + + if (ecma_number_is_nan (number)) + { + return ECMA_NUMBER_ZERO; + } + + if (ecma_number_is_zero (number) || ecma_number_is_infinity (number)) + { + return number; + } + + ecma_number_t floor_fabs = (ecma_number_t) floor (fabs (number)); + + return ecma_number_is_negative (number) ? -floor_fabs : floor_fabs; +} /* jerry_value_as_integer */ + +/** + * Convert any number to int32 number. + * + * Note: + * For non-number values 0 is returned. + * + * @return int32 representation of the number. + */ +int32_t +jerry_value_as_int32 (const jerry_value_t value) /**< input value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + return ecma_number_to_int32 (ecma_get_number_from_value (value)); +} /* jerry_value_as_int32 */ + +/** + * Convert any number to uint32 number. + * + * Note: + * For non-number values 0 is returned. + * + * @return uint32 representation of the number. + */ +uint32_t +jerry_value_as_uint32 (const jerry_value_t value) /**< input value */ +{ + if (!ecma_is_value_number (value)) + { + return 0; + } + + return ecma_number_to_uint32 (ecma_get_number_from_value (value)); +} /* jerry_value_as_uint32 */ + +/** + * Take additional ownership over the argument value. + * The value will be copied by reference when possible, changes made to the new value will be reflected + * in the original. + * + * @return copied value + */ +jerry_value_t +jerry_value_copy (const jerry_value_t value) /**< value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value)); + return value; + } + + return ecma_copy_value (value); +} /* jerry_value_copy */ + +/** + * Release ownership of the argument value + */ +void +jerry_value_free (jerry_value_t value) /**< value */ +{ + if (JERRY_UNLIKELY (ecma_is_value_exception (value))) + { + ecma_deref_exception (ecma_get_extended_primitive_from_value (value)); + return; + } + + ecma_free_value (value); +} /* jerry_value_free */ + +/** + * Create an array object value + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the constructed array object + */ +jerry_value_t +jerry_array (jerry_length_t length) /**< length of array */ +{ + ecma_object_t *array_p = ecma_op_new_array_object (length); + return ecma_make_object_value (array_p); +} /* jerry_array */ + +/** + * Create a jerry_value_t representing a boolean value from the given boolean parameter. + * + * @return value of the created boolean + */ +jerry_value_t +jerry_boolean (bool value) /**< bool value from which a jerry_value_t will be created */ +{ + return ecma_make_boolean_value (value); +} /* jerry_boolean */ + +/** + * Create an Error object with the provided string value as the error message. + * If the message value is not a string, the created error will not have a message property. + * + * @return Error object + */ +jerry_value_t +jerry_error (jerry_error_t error_type, /**< type of error */ + const jerry_value_t message) /**< message of the error */ +{ + ecma_string_t *message_p = NULL; + if (ecma_is_value_string (message)) + { + message_p = ecma_get_string_from_value (message); + } + + ecma_object_t *error_object_p = ecma_new_standard_error ((jerry_error_t) error_type, message_p); + + return ecma_make_object_value (error_object_p); +} /* jerry_error */ + +/** + * Create an Error object with a zero-terminated string as a message. If the message string is NULL, the created error + * will not have a message property. + * + * @return Error object + */ +jerry_value_t +jerry_error_sz (jerry_error_t error_type, /**< type of error */ + const char *message_p) /**< value of 'message' property + * of constructed error object */ +{ + jerry_value_t message = ECMA_VALUE_UNDEFINED; + + if (message_p != NULL) + { + message = jerry_string_sz (message_p); + } + + ecma_value_t error = jerry_error (error_type, message); + ecma_free_value (message); + + return error; +} /* jerry_error_sz */ + +/** + * Create an exception by constructing an Error object with the specified type and the provided string value as the + * error message. If the message value is not a string, the created error will not have a message property. + * + * @return exception value + */ +jerry_value_t +jerry_throw (jerry_error_t error_type, /**< type of error */ + const jerry_value_t message) /**< message value */ +{ + return jerry_throw_value (jerry_error (error_type, message), true); +} /* jerry_throw */ + +/** + * Create an exception by constructing an Error object with the specified type and the provided zero-terminated ASCII + * string as the error message. If the message string is NULL, the created error will not have a message property. + * + * @return exception value + */ +jerry_value_t +jerry_throw_sz (jerry_error_t error_type, /**< type of error */ + const char *message_p) /**< value of 'message' property + * of constructed error object */ +{ + return jerry_throw_value (jerry_error_sz (error_type, message_p), true); +} /* jerry_throw_sz */ + +/** + * Create an external function object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the constructed function object + */ +jerry_value_t +jerry_function_external (jerry_external_handler_t handler) /**< native handler + * for the function */ +{ + ecma_object_t *func_obj_p = ecma_op_create_external_function_object (handler); + return ecma_make_object_value (func_obj_p); +} /* jerry_function_external */ + +/** + * Creates a jerry_value_t representing a number value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return jerry_value_t created from the given double argument. + */ +jerry_value_t +jerry_number (double value) /**< double value from which a jerry_value_t will be created */ +{ + return ecma_make_number_value ((ecma_number_t) value); +} /* jerry_number */ + +/** + * Creates a jerry_value_t representing a positive or negative infinity value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return jerry_value_t representing an infinity value. + */ +jerry_value_t +jerry_infinity (bool sign) /**< true for negative Infinity + * false for positive Infinity */ +{ + return ecma_make_number_value (ecma_number_make_infinity (sign)); +} /* jerry_infinity */ + +/** + * Creates a jerry_value_t representing a not-a-number value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return jerry_value_t representing a not-a-number value. + */ +jerry_value_t +jerry_nan (void) +{ + return ecma_make_nan_value (); +} /* jerry_nan */ + +/** + * Creates a jerry_value_t representing an undefined value. + * + * @return value of undefined + */ +jerry_value_t +jerry_undefined (void) +{ + return ECMA_VALUE_UNDEFINED; +} /* jerry_undefined */ + +/** + * Creates and returns a jerry_value_t with type null object. + * + * @return jerry_value_t representing null + */ +jerry_value_t +jerry_null (void) +{ + return ECMA_VALUE_NULL; +} /* jerry_null */ + +/** + * Create new JavaScript object, like with new Object(). + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created object + */ +jerry_value_t +jerry_object (void) +{ + return ecma_make_object_value (ecma_op_create_object_object_noarg ()); +} /* jerry_object */ + +/** + * Create an empty Promise object which can be resolved/rejected later + * by calling jerry_promise_resolve or jerry_promise_reject. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created object + */ +jerry_value_t +jerry_promise (void) +{ + return jerry_return (ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL)); +} /* jerry_create_promise */ + +/** + * Create a new Proxy object with the given target and handler + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created Proxy object + */ +jerry_value_t +jerry_proxy (const jerry_value_t target, /**< target argument */ + const jerry_value_t handler) /**< handler argument */ +{ + if (ecma_is_value_exception (target) || ecma_is_value_exception (handler)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + +#if JERRY_BUILTIN_PROXY + ecma_object_t *proxy_p = ecma_proxy_create (target, handler, 0); + + if (proxy_p == NULL) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_object_value (proxy_p); +#else /* !JERRY_BUILTIN_PROXY */ + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PROXY_IS_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_PROXY */ +} /* jerry_proxy */ + +#if JERRY_BUILTIN_PROXY + +JERRY_STATIC_ASSERT (((int) JERRY_PROXY_SKIP_RESULT_VALIDATION == (int) ECMA_PROXY_SKIP_RESULT_VALIDATION), + jerry_and_ecma_proxy_skip_result_validation_must_be_equal); + +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * Create a new Proxy object with the given target, handler, and special options + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the created Proxy object + */ +jerry_value_t +jerry_proxy_custom (const jerry_value_t target, /**< target argument */ + const jerry_value_t handler, /**< handler argument */ + uint32_t flags) /**< jerry_proxy_custom_behavior_t option bits */ +{ + if (ecma_is_value_exception (target) || ecma_is_value_exception (handler)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + +#if JERRY_BUILTIN_PROXY + flags &= JERRY_PROXY_SKIP_RESULT_VALIDATION; + + ecma_object_t *proxy_p = ecma_proxy_create (target, handler, flags); + + if (proxy_p == NULL) + { + return ecma_create_exception_from_context (); + } + + return ecma_make_object_value (proxy_p); +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (flags); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PROXY_IS_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_PROXY */ +} /* jerry_proxy_custom */ + +/** + * Create string value from the input zero-terminated ASCII string. + * + * @return created string + */ +jerry_value_t +jerry_string_sz (const char *str_p) /**< pointer to string */ +{ + const jerry_char_t *data_p = (const jerry_char_t *) str_p; + return jerry_string (data_p, lit_zt_utf8_string_size (data_p), JERRY_ENCODING_CESU8); +} /* jerry_string_sz */ + +/** + * Create a string value from the input buffer using the specified encoding. + * The content of the buffer is assumed to be valid in the specified encoding, it's the callers responsibility to + * validate the input. + * + * See also: jerry_validate_string + * + * @return created string + */ +jerry_value_t +jerry_string (const jerry_char_t *buffer_p, /**< pointer to buffer */ + jerry_size_t buffer_size, /**< buffer size */ + jerry_encoding_t encoding) /**< buffer encoding */ +{ + ecma_string_t *ecma_str_p = NULL; + JERRY_ASSERT (jerry_validate_string (buffer_p, buffer_size, encoding)); + + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + ecma_str_p = ecma_new_ecma_string_from_utf8 (buffer_p, buffer_size); + break; + } + case JERRY_ENCODING_UTF8: + { + ecma_str_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (buffer_p, buffer_size); + break; + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INVALID_ENCODING)); + } + } + + return ecma_make_string_value (ecma_str_p); +} /* jerry_string */ + +/** + * Create external string from input zero-terminated ASCII string. + * + * @return created external string + */ +jerry_value_t +jerry_string_external_sz (const char *str_p, /**< pointer to string */ + void *user_p) /**< user pointer passed to the callback when the string is freed */ +{ + const jerry_char_t *data_p = (const jerry_char_t *) str_p; + return jerry_string_external (data_p, lit_zt_utf8_string_size (data_p), user_p); +} /* jerry_string_external_sz */ + +/** + * Create external string from a valid CESU-8 encoded string. + * The content of the buffer is assumed be encoded correctly, it's the callers responsibility to + * validate the input. + * + * See also: jerry_validate_string + * + * @return created external string + */ +jerry_value_t +jerry_string_external (const jerry_char_t *buffer_p, /**< pointer to string */ + jerry_size_t buffer_size, /**< string size */ + void *user_p) /**< user pointer passed to the callback when the string is freed */ +{ + JERRY_ASSERT (jerry_validate_string (buffer_p, buffer_size, JERRY_ENCODING_CESU8)); + ecma_string_t *ecma_str_p = ecma_new_ecma_external_string_from_cesu8 (buffer_p, buffer_size, user_p); + return ecma_make_string_value (ecma_str_p); +} /* jerry_string_external_sz_sz */ + +/** + * Create symbol with a description value + * + * Note: The given argument is converted to string. This operation can throw an exception. + * + * @return created symbol, + * or thrown exception + */ +jerry_value_t +jerry_symbol_with_description (const jerry_value_t value) /**< api value */ +{ + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return jerry_return (ecma_op_create_symbol (&value, 1)); +} /* jerry_create_symbol */ + +/** + * Create BigInt from a sequence of uint64 digits. + * + * Note: This operation can throw an exception. + * + * @return created bigint, + * or thrown exception + */ +jerry_value_t +jerry_bigint (const uint64_t *digits_p, /**< BigInt digits (lowest digit first) */ + uint32_t digit_count, /**< number of BigInt digits */ + bool sign) /**< sign bit, true if the result should be negative */ +{ +#if JERRY_BUILTIN_BIGINT + return jerry_return (ecma_bigint_create_from_digits (digits_p, digit_count, sign)); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (digits_p); + JERRY_UNUSED (digit_count); + JERRY_UNUSED (sign); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_BIGINT_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_bigint */ + +/** + * Creates a RegExp object with the given ASCII pattern and flags. + * + * @return value of the constructed RegExp object. + */ +jerry_value_t +jerry_regexp_sz (const char *pattern_p, /**< RegExp pattern as zero-terminated ASCII string */ + uint16_t flags) /**< RegExp flags */ +{ + jerry_value_t pattern = jerry_string_sz (pattern_p); + jerry_value_t result = jerry_regexp (pattern, flags); + + jerry_value_free (pattern); + return jerry_return (result); +} /* jerry_regexp_sz */ + +/** + * Creates a RegExp object with the given pattern and flags. + * + * @return value of the constructed RegExp object. + */ +jerry_value_t +jerry_regexp (const jerry_value_t pattern, /**< pattern string */ + uint16_t flags) /**< RegExp flags */ +{ +#if JERRY_BUILTIN_REGEXP + if (!ecma_is_value_string (pattern)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (regexp_obj_p == NULL)) + { + return ecma_create_exception_from_context (); + } + + jerry_value_t result = ecma_op_create_regexp_with_flags (regexp_obj_p, pattern, flags); + + return jerry_return (result); + +#else /* !JERRY_BUILTIN_REGEXP */ + JERRY_UNUSED (pattern); + JERRY_UNUSED (flags); + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_REGEXP_IS_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_REGEXP */ +} /* jerry_regexp */ + +/** + * Creates a new realm (global object). + * + * @return new realm object + */ +jerry_value_t +jerry_realm (void) +{ +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *global_object_p = ecma_builtin_create_global_object (); + return ecma_make_object_value ((ecma_object_t *) global_object_p); +#else /* !JERRY_BUILTIN_REALMS */ + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_REALMS_ARE_DISABLED)); +#endif /* JERRY_BUILTIN_REALMS */ +} /* jerry_realm */ + +/** + * Get length of an array object + * + * Note: + * Returns 0, if the value parameter is not an array object. + * + * @return length of the given array + */ +jerry_length_t +jerry_array_length (const jerry_value_t value) /**< api value */ +{ + if (!jerry_value_is_object (value)) + { + return 0; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + + if (JERRY_LIKELY (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY)) + { + return ecma_array_get_length (object_p); + } + + return 0; +} /* jerry_array_length */ + +/** + * Get the size of a string value in the specified encoding. + * + * @return number of bytes required by the string, + * 0 - if value is not a string + */ +jerry_size_t +jerry_string_size (const jerry_value_t value, /**< input string */ + jerry_encoding_t encoding) /**< encoding */ +{ + if (!ecma_is_value_string (value)) + { + return 0; + } + + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + return ecma_string_get_size (ecma_get_string_from_value (value)); + } + case JERRY_ENCODING_UTF8: + { + return ecma_string_get_utf8_size (ecma_get_string_from_value (value)); + } + default: + { + return 0; + } + } +} /* jerry_string_size */ + +/** + * Get length of a string value + * + * @return number of characters in the string + * 0 - if value is not a string + */ +jerry_length_t +jerry_string_length (const jerry_value_t value) /**< input string */ +{ + if (!ecma_is_value_string (value)) + { + return 0; + } + + return ecma_string_get_length (ecma_get_string_from_value (value)); +} /* jerry_string_length */ + +/** + * Copy the characters of a string into the specified buffer using the specified encoding. The string is truncated to + * fit the buffer. If the value is not a string, nothing will be copied to the buffer. + * + * @return number of bytes copied to the buffer + */ +jerry_size_t +jerry_string_to_buffer (const jerry_value_t value, /**< input string value */ + jerry_encoding_t encoding, /**< output encoding */ + jerry_char_t *buffer_p, /**< [out] output characters buffer */ + jerry_size_t buffer_size) /**< size of output buffer */ +{ + if (!ecma_is_value_string (value) || buffer_p == NULL) + { + return 0; + } + + ecma_string_t *str_p = ecma_get_string_from_value (value); + + return ecma_string_copy_to_buffer (str_p, (lit_utf8_byte_t *) buffer_p, buffer_size, encoding); +} /* jerry_string_to_char_buffer */ + +/** + * Create a substring of the input string value. + * Return an empty string if input value is not a string. + * + * @param value the input string value + * @param start start position of the substring + * @param end end position of the substring + * + * @return created string + */ +jerry_value_t +jerry_string_substr (const jerry_value_t value, jerry_length_t start, jerry_length_t end) +{ + if (!ecma_is_value_string (value)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + return ecma_make_string_value (ecma_string_substr (ecma_get_string_from_value (value), start, end)); +} /* jerry_string_substr */ + +/** + * Iterate over the input string value in the specified encoding, visiting each unit of the encoded string once. If + * the input value is not a string, the function will do nothing. + * + * @param value the input string value + * @param callback callback function called for each byte of the encoded string. + * @param encoding the requested encoding for the string + * @param user_p User pointer passed to the callback function + */ +void +jerry_string_iterate (const jerry_value_t value, + jerry_encoding_t encoding, + jerry_string_iterate_cb_t callback, + void *user_p) +{ + if (!ecma_is_value_string (value)) + { + return; + } + + ecma_string_t *str_p = ecma_get_string_from_value (value); + ECMA_STRING_TO_UTF8_STRING (str_p, buffer_p, buffer_size); + + const lit_utf8_byte_t *current_p = buffer_p; + const lit_utf8_byte_t *end_p = buffer_p + buffer_size; + + switch (encoding) + { + case JERRY_ENCODING_UTF8: + { + while (current_p < end_p) + { + if (JERRY_UNLIKELY (*current_p >= LIT_UTF8_3_BYTE_MARKER)) + { + lit_code_point_t cp; + lit_utf8_size_t read_size = lit_read_code_point_from_cesu8 (current_p, end_p, &cp); + + lit_utf8_byte_t bytes[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; + lit_utf8_size_t encoded_size = lit_code_point_to_utf8 (cp, bytes); + + for (uint32_t i = 0; i < encoded_size; i++) + { + callback (bytes[i], user_p); + } + + current_p += read_size; + continue; + } + + callback (*current_p++, user_p); + } + + break; + } + case JERRY_ENCODING_CESU8: + { + while (current_p < end_p) + { + callback (*current_p++, user_p); + } + + break; + } + default: + { + break; + } + } + ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size); +} /* jerry_string_iterate */ + +/** + * Sets the global callback which is called when an external string is freed. + */ +void +jerry_string_external_on_free (jerry_external_string_free_cb_t callback) /**< free callback */ +{ + JERRY_CONTEXT (external_string_free_callback_p) = callback; +} /* jerry_string_external_on_free */ + +/** + * Returns the user pointer assigned to an external string. + * + * @return user pointer, if value is an external string + * NULL, otherwise + */ +void * +jerry_string_user_ptr (const jerry_value_t value, /**< string value */ + bool *is_external) /**< [out] true - if value is an external string, + * false - otherwise */ +{ + if (is_external != NULL) + { + *is_external = false; + } + + if (!ecma_is_value_string (value)) + { + return NULL; + } + + ecma_string_t *string_p = ecma_get_string_from_value (value); + + if (ECMA_IS_DIRECT_STRING (string_p) + || ECMA_STRING_GET_CONTAINER (string_p) != ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + return NULL; + } + + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + + if (long_string_p->string_p == ECMA_LONG_STRING_BUFFER_START (long_string_p)) + { + return NULL; + } + + if (is_external != NULL) + { + *is_external = true; + } + + return ((ecma_external_string_t *) string_p)->user_p; +} /* jerry_string_user_ptr */ + +/** + * Checks whether the object or it's prototype objects have the given property. + * + * @return raised error - if the operation fail + * true/false API value - depend on whether the property exists + */ +jerry_value_t +jerry_object_has (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); + + return jerry_return (ecma_op_object_has_property (obj_p, prop_name_p)); +} /* jerry_object_has */ + +/** + * Checks whether the object or it's prototype objects have the given property. + * + * @return raised error - if the operation fail + * true/false API value - depend on whether the property exists + */ +jerry_value_t +jerry_object_has_sz (const jerry_value_t object, /**< object value */ + const char *key_p) /**< property key */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_has (object, key_str); + ecma_free_value (key_str); + + return result; +} /* jerry_object_has */ + +/** + * Checks whether the object has the given property. + * + * @return ECMA_VALUE_ERROR - if the operation raises error + * ECMA_VALUE_{TRUE, FALSE} - based on whether the property exists + */ +jerry_value_t +jerry_object_has_own (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); + + return jerry_return (ecma_op_object_has_own_property (obj_p, prop_name_p)); +} /* jerry_has_own_property */ + +/** + * Checks whether the object has the given internal property. + * + * @return true - if the internal property exists + * false - otherwise + */ +bool +jerry_object_has_internal (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name value */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + return false; + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + + if (property_p == NULL) + { + return false; + } + + ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (key)); + + return property_p != NULL; +} /* jerry_object_has_internal */ + +/** + * Delete a property from an object. + * + * @return boolean value - wether the property was deleted successfully + * exception - otherwise + */ +jerry_value_t +jerry_object_delete (jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + return ecma_op_object_delete (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), false); +} /* jerry_object_delete */ + +/** + * Delete a property from an object. + * + * @return boolean value - wether the property was deleted successfully + * exception - otherwise + */ +jerry_value_t +jerry_object_delete_sz (jerry_value_t object, /**< object value */ + const char *key_p) /**< property key */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_delete (object, key_str); + ecma_free_value (key_str); + + return result; +} /* jerry_object_delete */ + +/** + * Delete indexed property from the specified object. + * + * @return boolean value - wether the property was deleted successfully + * false - otherwise + */ +jerry_value_t +jerry_object_delete_index (jerry_value_t object, /**< object value */ + uint32_t index) /**< index to be written */ +{ + if (!ecma_is_value_object (object)) + { + return false; + } + + ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index); + ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (object), str_idx_p, false); + ecma_deref_ecma_string (str_idx_p); + + return ret_value; +} /* jerry_object_delete_index */ + +/** + * Delete an internal property from an object. + * + * @return true - if property was deleted successfully + * false - otherwise + */ +bool +jerry_object_delete_internal (jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name value */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + return true; + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + + if (property_p == NULL) + { + return true; + } + + ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (key)); + + if (property_p == NULL) + { + return true; + } + + ecma_delete_property (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p)); + + return true; +} /* jerry_object_delete_internal */ + +/** + * Get value of a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name (string value) */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + jerry_value_t ret_value = + ecma_op_object_get (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key)); + return jerry_return (ret_value); +} /* jerry_object_get */ + +/** + * Get value of a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get_sz (const jerry_value_t object, /**< object value */ + const char *key_p) /**< property key */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_get (object, key_str); + ecma_free_value (key_str); + + return result; +} /* jerry_object_get */ + +/** + * Get value by an index from the specified object. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property specified by the index - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get_index (const jerry_value_t object, /**< object value */ + uint32_t index) /**< index to be written */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_value_t ret_value = ecma_op_object_get_by_index (ecma_get_object_from_value (object), index); + + return jerry_return (ret_value); +} /* jerry_object_get_index */ + +/** + * Get the own property value of an object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the property - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_find_own (const jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + const jerry_value_t receiver, /**< receiver object value */ + bool *found_p) /**< [out] true, if the property is found + * or object is a Proxy object, false otherwise */ +{ + if (found_p != NULL) + { + *found_p = false; + } + + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key) || !ecma_is_value_object (receiver)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *object_p = ecma_get_object_from_value (object); + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (key); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + if (found_p != NULL) + { + *found_p = true; + } + + return jerry_return (ecma_proxy_object_get (object_p, property_name_p, receiver)); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t ret_value = ecma_op_object_find_own (receiver, object_p, property_name_p); + + if (ecma_is_value_found (ret_value)) + { + if (found_p != NULL) + { + *found_p = true; + } + + return jerry_return (ret_value); + } + + return ECMA_VALUE_UNDEFINED; +} /* jerry_object_find_own */ + +/** + * Get value of an internal property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return value of the internal property - if the internal property exists + * undefined value - if the internal does not property exists + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_get_internal (const jerry_value_t object, /**< object value */ + const jerry_value_t key) /**< property name value */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + return jerry_return (ECMA_VALUE_UNDEFINED); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + + if (property_p == NULL) + { + return jerry_return (ECMA_VALUE_UNDEFINED); + } + + ecma_object_t *internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + property_p = ecma_find_named_property (internal_object_p, ecma_get_prop_name_from_value (key)); + + if (property_p == NULL) + { + return jerry_return (ECMA_VALUE_UNDEFINED); + } + + return jerry_return (ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value)); +} /* jerry_object_get_internal */ + +/** + * Set a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set (jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + const jerry_value_t value) /**< value to set */ +{ + if (ecma_is_value_exception (value) || !ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return jerry_return ( + ecma_op_object_put (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), value, true)); +} /* jerry_object_set */ + +/** + * Set a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set_sz (jerry_value_t object, /**< object value */ + const char *key_p, /**< property key */ + const jerry_value_t value) /**< value to set */ +{ + jerry_value_t key_str = jerry_string_sz (key_p); + jerry_value_t result = jerry_object_set (object, key_str, value); + ecma_free_value (key_str); + + return result; +} /* jerry_object_set */ + +/** + * Set indexed value in the specified object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set_index (jerry_value_t object, /**< object value */ + uint32_t index, /**< index to be written */ + const jerry_value_t value) /**< value to set */ +{ + if (ecma_is_value_exception (value) || !ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_value_t ret_value = ecma_op_object_put_by_index (ecma_get_object_from_value (object), index, value, true); + + return jerry_return (ret_value); +} /* jerry_object_set_index */ + +/** + * Set an internal property to the specified object with the given name. + * + * Note: + * - the property cannot be accessed from the JavaScript context, only from the public API + * - returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * value marked with error flag - otherwise + */ +bool +jerry_object_set_internal (jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name value */ + const jerry_value_t value) /**< value to set */ +{ + if (ecma_is_value_exception (value) || !ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + ecma_string_t *internal_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_API_INTERNAL); + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, internal_string_p); + ecma_object_t *internal_object_p; + + if (property_p == NULL) + { + ecma_property_value_t *value_p = + ecma_create_named_data_property (obj_p, internal_string_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + + internal_object_p = ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + { + ecma_extended_object_t *container_p = (ecma_extended_object_t *) internal_object_p; + container_p->u.cls.type = ECMA_OBJECT_CLASS_INTERNAL_OBJECT; + } + + value_p->value = ecma_make_object_value (internal_object_p); + ecma_deref_object (internal_object_p); + } + else + { + internal_object_p = ecma_get_object_from_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + } + + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); + property_p = ecma_find_named_property (internal_object_p, prop_name_p); + + if (property_p == NULL) + { + ecma_property_value_t *value_p = ecma_create_named_data_property (internal_object_p, + prop_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + value_p->value = ecma_copy_value_if_not_object (value); + } + else + { + ecma_named_data_property_assign_value (internal_object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + } + + return true; +} /* jerry_object_set_internal */ + +/** + * Construct empty property descriptor, i.e.: + * property descriptor with all is_defined flags set to false and the rest - to default value. + * + * @return empty property descriptor + */ +jerry_property_descriptor_t +jerry_property_descriptor (void) +{ + jerry_property_descriptor_t prop_desc; + + prop_desc.flags = JERRY_PROP_NO_OPTS; + prop_desc.value = ECMA_VALUE_UNDEFINED; + prop_desc.getter = ECMA_VALUE_UNDEFINED; + prop_desc.setter = ECMA_VALUE_UNDEFINED; + + return prop_desc; +} /* jerry_property_descriptor */ + +/** + * Convert a ecma_property_descriptor_t to a jerry_property_descriptor_t + * + * if error occurs the property descriptor's value field is filled with ECMA_VALUE_ERROR + * + * @return jerry_property_descriptor_t + */ +static jerry_property_descriptor_t +jerry_property_descriptor_from_ecma (const ecma_property_descriptor_t *prop_desc_p) /**<[out] property_descriptor */ +{ + jerry_property_descriptor_t prop_desc = jerry_property_descriptor (); + + prop_desc.flags = prop_desc_p->flags; + + if (prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED)) + { + prop_desc.value = prop_desc_p->value; + } + + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + prop_desc.getter = ECMA_VALUE_NULL; + + if (prop_desc_p->get_p != NULL) + { + prop_desc.getter = ecma_make_object_value (prop_desc_p->get_p); + JERRY_ASSERT (ecma_op_is_callable (prop_desc.getter)); + } + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + prop_desc.setter = ECMA_VALUE_NULL; + + if (prop_desc_p->set_p != NULL) + { + prop_desc.setter = ecma_make_object_value (prop_desc_p->set_p); + JERRY_ASSERT (ecma_op_is_callable (prop_desc.setter)); + } + } + + return prop_desc; +} /* jerry_property_descriptor_from_ecma */ + +/** + * Convert a jerry_property_descriptor_t to a ecma_property_descriptor_t + * + * Note: + * if error occurs the property descriptor's value field + * is set to ECMA_VALUE_ERROR, but no error is thrown + * + * @return ecma_property_descriptor_t + */ +static ecma_property_descriptor_t +jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_p) /**< input property_descriptor */ +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + prop_desc.flags = prop_desc_p->flags; + + /* Copy data property info. */ + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + if (ecma_is_value_exception (prop_desc_p->value) + || (prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + prop_desc.value = prop_desc_p->value; + } + + /* Copy accessor property info. */ + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + ecma_value_t getter = prop_desc_p->getter; + + if (ecma_is_value_exception (getter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + if (ecma_op_is_callable (getter)) + { + prop_desc.get_p = ecma_get_object_from_value (getter); + } + else if (!ecma_is_value_null (getter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + ecma_value_t setter = prop_desc_p->setter; + + if (ecma_is_value_exception (setter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + if (ecma_op_is_callable (setter)) + { + prop_desc.set_p = ecma_get_object_from_value (setter); + } + else if (!ecma_is_value_null (setter)) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + } + + const uint16_t configurable_mask = JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED; + const uint16_t enumerable_mask = JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED; + const uint16_t writable_mask = JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED; + + if ((prop_desc_p->flags & configurable_mask) == JERRY_PROP_IS_CONFIGURABLE + || (prop_desc_p->flags & enumerable_mask) == JERRY_PROP_IS_ENUMERABLE + || (prop_desc_p->flags & writable_mask) == JERRY_PROP_IS_WRITABLE) + { + prop_desc.value = ECMA_VALUE_ERROR; + return prop_desc; + } + + prop_desc.flags |= (uint16_t) (prop_desc_p->flags | JERRY_PROP_SHOULD_THROW); + + return prop_desc; +} /* jerry_property_descriptor_to_ecma */ + +/** Helper function to return false value or error depending on the given flag. + * + * @return value marked with error flag - if is_throw is true + * false value - otherwise + */ +static jerry_value_t +jerry_type_error_or_false (ecma_error_msg_t msg, /**< message */ + uint16_t flags) /**< property descriptor flags */ +{ + if (!(flags & JERRY_PROP_SHOULD_THROW)) + { + return ECMA_VALUE_FALSE; + } + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (msg)); +} /* jerry_type_error_or_false */ + +/** + * Define a property to the specified object with the given name. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return true value - if the operation was successful + * false value - if the property cannot be defined and JERRY_PROP_SHOULD_THROW is not set + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_define_own_prop (jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + const jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return jerry_type_error_or_false (ECMA_ERR_WRONG_ARGS_MSG, prop_desc_p->flags); + } + + if (prop_desc_p->flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_VALUE_DEFINED) + && prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + return jerry_type_error_or_false (ECMA_ERR_WRONG_ARGS_MSG, prop_desc_p->flags); + } + + ecma_property_descriptor_t prop_desc = jerry_property_descriptor_to_ecma (prop_desc_p); + + if (ECMA_IS_VALUE_ERROR (prop_desc.value)) + { + return jerry_type_error_or_false (ECMA_ERR_WRONG_ARGS_MSG, prop_desc_p->flags); + } + + return jerry_return (ecma_op_object_define_own_property (ecma_get_object_from_value (object), + ecma_get_prop_name_from_value (key), + &prop_desc)); +} /* jerry_object_define_own_prop */ + +/** + * Construct property descriptor from specified property. + * + * @return true - if success, the prop_desc_p fields contains the property info + * false - otherwise, the prop_desc_p is unchanged + */ +jerry_value_t +jerry_object_get_own_prop (const jerry_value_t object, /**< object value */ + const jerry_value_t key, /**< property name (string value) */ + jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (!ecma_is_value_object (object) || !ecma_is_value_prop_name (key)) + { + return ECMA_VALUE_FALSE; + } + + ecma_property_descriptor_t prop_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (object), + ecma_get_prop_name_from_value (key), + &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (!ecma_is_value_true (status)) + { + return ECMA_VALUE_FALSE; + } + + /* The flags are always filled in the returned descriptor. */ + JERRY_ASSERT ( + (prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) && (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && ((prop_desc.flags & JERRY_PROP_IS_WRITABLE_DEFINED) || !(prop_desc.flags & JERRY_PROP_IS_VALUE_DEFINED))); + + prop_desc_p->flags = prop_desc.flags; + prop_desc_p->value = ECMA_VALUE_UNDEFINED; + prop_desc_p->getter = ECMA_VALUE_UNDEFINED; + prop_desc_p->setter = ECMA_VALUE_UNDEFINED; + + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + prop_desc_p->value = prop_desc.value; + } + + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + if (prop_desc.get_p != NULL) + { + prop_desc_p->getter = ecma_make_object_value (prop_desc.get_p); + } + else + { + prop_desc_p->getter = ECMA_VALUE_NULL; + } + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + if (prop_desc.set_p != NULL) + { + prop_desc_p->setter = ecma_make_object_value (prop_desc.set_p); + } + else + { + prop_desc_p->setter = ECMA_VALUE_NULL; + } + } + + return ECMA_VALUE_TRUE; +} /* jerry_object_get_own_prop */ + +/** + * Free fields of property descriptor (setter, getter and value). + */ +void +jerry_property_descriptor_free (jerry_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + jerry_value_free (prop_desc_p->value); + } + + if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + jerry_value_free (prop_desc_p->getter); + } + + if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + jerry_value_free (prop_desc_p->setter); + } +} /* jerry_property_descriptor_free */ + +/** + * Call function specified by a function value + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * error flag must not be set for any arguments of this function. + * + * @return returned jerry value of the called function + */ +jerry_value_t +jerry_call (const jerry_value_t func_object, /**< function object to call */ + const jerry_value_t this_value, /**< object for 'this' binding */ + const jerry_value_t *args_p, /**< function's call arguments */ + jerry_size_t args_count) /**< number of the arguments */ +{ + if (ecma_is_value_exception (this_value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + for (jerry_size_t i = 0; i < args_count; i++) + { + if (ecma_is_value_exception (args_p[i])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + } + + return jerry_return (ecma_op_function_validated_call (func_object, this_value, args_p, args_count)); +} /* jerry_call */ + +/** + * Construct object value invoking specified function value as a constructor + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * error flag must not be set for any arguments of this function. + * + * @return returned jerry value of the invoked constructor + */ +jerry_value_t +jerry_construct (const jerry_value_t func_object, /**< function object to call */ + const jerry_value_t *args_p, /**< function's call arguments + * (NULL if arguments number is zero) */ + jerry_size_t args_count) /**< number of the arguments */ +{ + if (!jerry_value_is_constructor (func_object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + for (jerry_size_t i = 0; i < args_count; i++) + { + if (ecma_is_value_exception (args_p[i])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + } + + return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_object), + ecma_get_object_from_value (func_object), + args_p, + args_count)); +} /* jerry_construct */ + +/** + * Get keys of the specified object value + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return array object value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_keys (const jerry_value_t object) /**< object value */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_collection_t *prop_names = + ecma_op_object_get_enumerable_property_names (ecma_get_object_from_value (object), ECMA_ENUMERABLE_PROPERTY_KEYS); + +#if JERRY_BUILTIN_PROXY + if (JERRY_UNLIKELY (prop_names == NULL)) + { + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_op_new_array_object_from_collection (prop_names, false); +} /* jerry_object_keys */ + +/** + * Get the prototype of the specified object + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return prototype object or null value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_proto (const jerry_value_t object) /**< object value */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return jerry_return (ecma_proxy_object_get_prototype_of (obj_p)); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (obj_p->u2.prototype_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_NULL; + } + + ecma_object_t *proto_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_p->u2.prototype_cp); + ecma_ref_object (proto_obj_p); + + return ecma_make_object_value (proto_obj_p); +} /* jerry_object_proto */ + +/** + * Set the prototype of the specified object + * + * @return true value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_set_proto (jerry_value_t object, /**< object value */ + const jerry_value_t proto) /**< prototype object value */ +{ + if (!ecma_is_value_object (object) || ecma_is_value_exception (proto) + || (!ecma_is_value_object (proto) && !ecma_is_value_null (proto))) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + ecma_object_t *obj_p = ecma_get_object_from_value (object); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return jerry_return (ecma_proxy_object_set_prototype_of (obj_p, proto)); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_op_ordinary_object_set_prototype_of (obj_p, proto); +} /* jerry_object_set_proto */ + +/** + * Utility to check if a given object can be used for the foreach api calls. + * + * Some objects/classes uses extra internal objects to correctly store data. + * These extre object should never be exposed externally to the API user. + * + * @returns true - if the user can access the object in the callback. + * false - if the object is an internal object which should no be accessed by the user. + */ +static bool +jerry_object_is_valid_foreach (ecma_object_t *object_p) /**< object to test */ +{ + if (ecma_is_lexical_environment (object_p)) + { + return false; + } + + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + if (object_type == ECMA_OBJECT_TYPE_CLASS) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + switch (ext_object_p->u.cls.type) + { + /* An object's internal property object should not be iterable by foreach. */ + case ECMA_OBJECT_CLASS_INTERNAL_OBJECT: + { + return false; + } + } + } + + return true; +} /* jerry_object_is_valid_foreach */ + +/** + * Traverse objects. + * + * @return true - traversal was interrupted by the callback. + * false - otherwise - traversal visited all objects. + */ +bool +jerry_foreach_live_object (jerry_foreach_live_object_cb_t callback, /**< function pointer of the iterator function */ + void *user_data_p) /**< pointer to user data */ +{ + JERRY_ASSERT (callback != NULL); + + jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + while (iter_cp != JMEM_CP_NULL) + { + ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp); + + if (jerry_object_is_valid_foreach (iter_p) && !callback (ecma_make_object_value (iter_p), user_data_p)) + { + return true; + } + + iter_cp = iter_p->gc_next_cp; + } + + return false; +} /* jerry_foreach_live_object */ + +/** + * Traverse objects having a given native type info. + * + * @return true - traversal was interrupted by the callback. + * false - otherwise - traversal visited all objects. + */ +bool +jerry_foreach_live_object_with_info (const jerry_object_native_info_t *native_info_p, /**< the type info + * of the native pointer */ + jerry_foreach_live_object_with_info_cb_t callback, /**< function to apply for + * each matching object */ + void *user_data_p) /**< pointer to user data */ +{ + JERRY_ASSERT (native_info_p != NULL); + JERRY_ASSERT (callback != NULL); + + ecma_native_pointer_t *native_pointer_p; + + jmem_cpointer_t iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + while (iter_cp != JMEM_CP_NULL) + { + ecma_object_t *iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, iter_cp); + + if (jerry_object_is_valid_foreach (iter_p)) + { + native_pointer_p = ecma_get_native_pointer_value (iter_p, (jerry_object_native_info_t *) native_info_p); + if (native_pointer_p && !callback (ecma_make_object_value (iter_p), native_pointer_p->native_p, user_data_p)) + { + return true; + } + } + + iter_cp = iter_p->gc_next_cp; + } + + return false; +} /* jerry_foreach_live_object_with_info */ + +/** + * Get native pointer and its type information, associated with the given native type info. + * + * Note: + * If native pointer is present, its type information is returned in out_native_pointer_p + * + * @return found native pointer, + * or NULL + */ +void * +jerry_object_get_native_ptr (const jerry_value_t object, /**< object to get native pointer from */ + const jerry_object_native_info_t *native_info_p) /**< the type info + * of the native pointer */ +{ + if (!ecma_is_value_object (object)) + { + return NULL; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_native_pointer_t *native_pointer_p = ecma_get_native_pointer_value (obj_p, (jerry_object_native_info_t *) native_info_p); + + if (native_pointer_p == NULL) + { + return NULL; + } + + return native_pointer_p->native_p; +} /* jerry_object_get_native_ptr */ + +/** + * Set native pointer and an optional type info for the specified object. + * + * + * Note: + * If native pointer was already set for the object, its value is updated. + * + * Note: + * If a non-NULL free callback is specified in the native type info, + * it will be called by the garbage collector when the object is freed. + * Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition) + * The type info always overwrites the previous value, so passing + * a NULL value deletes the current type info. + */ +void +jerry_object_set_native_ptr (jerry_value_t object, /**< object to set native pointer in */ + const jerry_object_native_info_t *native_info_p, /**< object's native type info */ + void *native_pointer_p) /**< native pointer */ +{ + if (ecma_is_value_object (object)) + { + ecma_object_t *object_p = ecma_get_object_from_value (object); + + ecma_create_native_pointer_property (object_p, native_pointer_p, native_info_p); + } +} /* jerry_object_set_native_ptr */ + +/** + * Checks wether the argument object has a native poitner set for the specified native type info. + * + * @return true if the native pointer has been set, + * false otherwise + */ +bool +jerry_object_has_native_ptr (const jerry_value_t object, /**< object to set native pointer in */ + const jerry_object_native_info_t *native_info_p) /**< object's native type info */ +{ + if (!ecma_is_value_object (object)) + { + return false; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_native_pointer_t *native_pointer_p = ecma_get_native_pointer_value (obj_p, (jerry_object_native_info_t *) native_info_p); + + return native_pointer_p != NULL; +} /* jerry_object_has_native_ptr */ + +/** + * Delete the previously set native pointer by the native type info from the specified object. + * + * Note: + * If the specified object has no matching native pointer for the given native type info + * the function has no effect. + * + * Note: + * This operation cannot throw an exception. + * + * @return true - if the native pointer has been deleted succesfully + * false - otherwise + */ +bool +jerry_object_delete_native_ptr (jerry_value_t object, /**< object to delete native pointer from */ + const jerry_object_native_info_t *native_info_p) /**< object's native type info */ +{ + if (ecma_is_value_object (object)) + { + ecma_object_t *object_p = ecma_get_object_from_value (object); + + return ecma_delete_native_pointer_property (object_p, (jerry_object_native_info_t *) native_info_p); + } + + return false; +} /* jerry_object_delete_native_ptr */ + +/** + * Initialize the references stored in a buffer pointed by a native pointer. + * The references are initialized to undefined. + */ +void +jerry_native_ptr_init (void *native_pointer_p, /**< a valid non-NULL pointer to a native buffer */ + const jerry_object_native_info_t *native_info_p) /**< the type info of + * the native pointer */ +{ + if (native_pointer_p == NULL || native_info_p == NULL) + { + return; + } + + ecma_value_t *value_p = (ecma_value_t *) (((uint8_t *) native_pointer_p) + native_info_p->offset_of_references); + ecma_value_t *end_p = value_p + native_info_p->number_of_references; + + while (value_p < end_p) + { + *value_p++ = ECMA_VALUE_UNDEFINED; + } +} /* jerry_native_ptr_init */ + +/** + * Release the value references after a buffer pointed by a native pointer + * is not attached to an object anymore. All references are set to undefined + * similar to jerry_native_ptr_init. + */ +void +jerry_native_ptr_free (void *native_pointer_p, /**< a valid non-NULL pointer to a native buffer */ + const jerry_object_native_info_t *native_info_p) /**< the type info of + * the native pointer */ +{ + if (native_pointer_p == NULL || native_info_p == NULL) + { + return; + } + + ecma_value_t *value_p = (ecma_value_t *) (((uint8_t *) native_pointer_p) + native_info_p->offset_of_references); + ecma_value_t *end_p = value_p + native_info_p->number_of_references; + + while (value_p < end_p) + { + ecma_free_value_if_not_object (*value_p); + *value_p++ = ECMA_VALUE_UNDEFINED; + } +} /* jerry_native_ptr_free */ + +/** + * Updates a value reference inside the area specified by the number_of_references and + * offset_of_references fields in its corresponding jerry_object_native_info_t data. + * The area must be part of a buffer which is currently assigned to an object. + * + * Note: + * Error references are not supported, they are replaced by undefined values. + */ +void +jerry_native_ptr_set (jerry_value_t *reference_p, /**< a valid non-NULL pointer to + * a reference in a native buffer. */ + const jerry_value_t value) /**< new value of the reference */ +{ + if (reference_p == NULL) + { + return; + } + + ecma_free_value_if_not_object (*reference_p); + + if (ecma_is_value_exception (value)) + { + *reference_p = ECMA_VALUE_UNDEFINED; + return; + } + + *reference_p = ecma_copy_value_if_not_object (value); +} /* jerry_native_ptr_set */ + +/** + * Applies the given function to the every property in the object. + * + * @return true - if object fields traversal was performed successfully, i.e.: + * - no unhandled exceptions were thrown in object fields traversal; + * - object fields traversal was stopped on callback that returned false; + * false - otherwise, + * if getter of field threw a exception or unhandled exceptions were thrown during traversal; + */ +bool +jerry_object_foreach (const jerry_value_t object, /**< object value */ + jerry_object_property_foreach_cb_t foreach_p, /**< foreach function */ + void *user_data_p) /**< user data for foreach function */ +{ + if (!ecma_is_value_object (object)) + { + return false; + } + + ecma_object_t *object_p = ecma_get_object_from_value (object); + ecma_collection_t *names_p = ecma_op_object_enumerate (object_p); + +#if JERRY_BUILTIN_PROXY + if (names_p == NULL) + { + // TODO: Due to Proxies the return value must be changed to jerry_value_t on next release + jcontext_release_exception (); + return false; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = names_p->buffer_p; + + ecma_value_t property_value = ECMA_VALUE_EMPTY; + + bool continuous = true; + + for (uint32_t i = 0; continuous && (i < names_p->item_count); i++) + { + ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); + + property_value = ecma_op_object_get (object_p, property_name_p); + + if (ECMA_IS_VALUE_ERROR (property_value)) + { + break; + } + + continuous = foreach_p (buffer_p[i], property_value, user_data_p); + ecma_free_value (property_value); + } + + ecma_collection_free (names_p); + + if (!ECMA_IS_VALUE_ERROR (property_value)) + { + return true; + } + + jcontext_release_exception (); + return false; +} /* jerry_object_foreach */ + +/** + * Gets the property keys for the given object using the selected filters. + * + * @return array containing the filtered property keys in successful operation + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_object_property_names (const jerry_value_t object, /**< object */ + jerry_property_filter_t filter) /**< property filter options */ +{ + if (!ecma_is_value_object (object)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + ecma_object_t *obj_iter_p = obj_p; + ecma_collection_t *result_p = ecma_new_collection (); + + ecma_ref_object (obj_iter_p); + + while (true) + { + /* Step 1. Get Object.[[OwnKeys]] */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p, filter); + +#if JERRY_BUILTIN_PROXY + if (prop_names_p == NULL) + { + ecma_deref_object (obj_iter_p); + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + ecma_value_t key = prop_names_p->buffer_p[i]; + ecma_string_t *key_p = ecma_get_prop_name_from_value (key); + uint32_t index = ecma_string_get_array_index (key_p); + + /* Step 2. Filter by key type */ + if (filter + & (JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS | JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS + | JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + if (ecma_is_value_symbol (key)) + { + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) + { + continue; + } + } + else if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if ((filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + || ((filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + && !(filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER))) + { + continue; + } + } + else if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + continue; + } + } + + /* Step 3. Filter property attributes */ + if (filter + & (JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE | JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE + | JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE)) + { + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_iter_p, key_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (prop_names_p); + ecma_collection_free (result_p); + ecma_deref_object (obj_iter_p); + return ecma_create_exception_from_context (); + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (ecma_is_value_true (status)); + uint16_t flags = prop_desc.flags; + ecma_free_property_descriptor (&prop_desc); + + if ((!(flags & JERRY_PROP_IS_CONFIGURABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE)) + || (!(flags & JERRY_PROP_IS_ENUMERABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE)) + || (!(flags & JERRY_PROP_IS_WRITABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE))) + { + continue; + } + } + + if (index != ECMA_STRING_NOT_ARRAY_INDEX && (filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER)) + { + ecma_deref_ecma_string (key_p); + key = ecma_make_uint32_value (index); + } + else + { + ecma_ref_ecma_string (key_p); + } + + if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) && obj_iter_p != obj_p) + { + uint32_t duplicate_idx = 0; + while (duplicate_idx < result_p->item_count) + { + ecma_value_t value = result_p->buffer_p[duplicate_idx]; + JERRY_ASSERT (ecma_is_value_prop_name (value) || ecma_is_value_number (value)); + if (JERRY_UNLIKELY (ecma_is_value_number (value))) + { + if (ecma_get_number_from_value (value) == ecma_get_number_from_value (key)) + { + break; + } + } + else if (ecma_compare_ecma_strings (ecma_get_prop_name_from_value (value), key_p)) + { + break; + } + + duplicate_idx++; + } + + if (duplicate_idx == result_p->item_count) + { + ecma_collection_push_back (result_p, key); + } + } + else + { + ecma_collection_push_back (result_p, key); + } + } + + ecma_collection_free (prop_names_p); + + /* Step 4: Traverse prototype chain */ + + if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) != JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) + { + break; + } + + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_iter_p); + + if (proto_p == NULL) + { + break; + } + + ecma_deref_object (obj_iter_p); + + if (JERRY_UNLIKELY (proto_p == ECMA_OBJECT_POINTER_ERROR)) + { + ecma_collection_free (result_p); + return ecma_create_exception_from_context (); + } + + obj_iter_p = proto_p; + } + + ecma_deref_object (obj_iter_p); + + return ecma_op_new_array_object_from_collection (result_p, false); +} /* jerry_object_property_names */ + +/** + * FromPropertyDescriptor abstract operation. + * + * @return new jerry_value_t - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_property_descriptor_to_object (const jerry_property_descriptor_t *src_prop_desc_p) /**< property descriptor */ +{ + ecma_property_descriptor_t prop_desc = jerry_property_descriptor_to_ecma (src_prop_desc_p); + + if (ECMA_IS_VALUE_ERROR (prop_desc.value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + + return ecma_make_object_value (desc_obj_p); +} /* jerry_property_descriptor_to_object */ + +/** + * ToPropertyDescriptor abstract operation. + * + * @return true - if the conversion is successful + * thrown error - otherwise + */ +jerry_value_t +jerry_property_descriptor_from_object (const jerry_value_t object, /**< object value */ + jerry_property_descriptor_t *out_prop_desc_p) /**< [out] filled property + * descriptor if return value is + * true, unmodified otherwise */ +{ + ecma_property_descriptor_t prop_desc; + jerry_value_t result = ecma_op_to_property_descriptor (object, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return ecma_create_exception_from_context (); + } + + JERRY_ASSERT (result == ECMA_VALUE_EMPTY); + + *out_prop_desc_p = jerry_property_descriptor_from_ecma (&prop_desc); + return ECMA_VALUE_TRUE; +} /* jerry_property_descriptor_from_object */ + +/** + * Resolve a promise value with an argument. + * + * @return undefined - if success, + * exception - otherwise + */ +jerry_value_t +jerry_promise_resolve (jerry_value_t promise, /**< the promise value */ + const jerry_value_t argument) /**< the argument */ +{ + if (!jerry_value_is_promise (promise)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + if (ecma_is_value_exception (argument)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return ecma_fulfill_promise_with_checks (promise, argument); +} /* jerry_promise_resolve */ + +/** + * Reject a promise value with an argument. + * + * @return undefined - if success, + * exception - otherwise + */ +jerry_value_t +jerry_promise_reject (jerry_value_t promise, /**< the promise value */ + const jerry_value_t argument) /**< the argument */ +{ + if (!jerry_value_is_promise (promise)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + if (ecma_is_value_exception (argument)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + return ecma_reject_promise_with_checks (promise, argument); +} /* jerry_promise_reject */ + +/** + * Get the result of a promise. + * + * @return - Promise result + * - Type error if the promise support was not enabled or the input was not a promise object + */ +jerry_value_t +jerry_promise_result (const jerry_value_t promise) /**< promise object to get the result from */ +{ + if (!jerry_value_is_promise (promise)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + return ecma_promise_get_result (ecma_get_object_from_value (promise)); +} /* jerry_get_promise_result */ + +/** + * Get the state of a promise object. + * + * @return - the state of the promise (one of the jerry_promise_state_t enum values) + * - JERRY_PROMISE_STATE_NONE is only returned if the input is not a promise object + * or the promise support was not enabled. + */ +jerry_promise_state_t +jerry_promise_state (const jerry_value_t promise) /**< promise object to get the state from */ +{ + if (!jerry_value_is_promise (promise)) + { + return JERRY_PROMISE_STATE_NONE; + } + + uint16_t flags = ecma_promise_get_flags (ecma_get_object_from_value (promise)); + flags &= (ECMA_PROMISE_IS_PENDING | ECMA_PROMISE_IS_FULFILLED); + + return (flags ? (jerry_promise_state_t) flags : JERRY_PROMISE_STATE_REJECTED); +} /* jerry_get_promise_state */ + +/** + * Sets a callback for tracking Promise and async operations. + * + * Note: + * the previous callback is overwritten + */ +void +jerry_promise_on_event (jerry_promise_event_filter_t filters, /**< combination of event filters */ + jerry_promise_event_cb_t callback, /**< notification callback */ + void *user_p) /**< user pointer passed to the callback */ +{ + JERRY_UNUSED (filters); + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +} /* jerry_promise_set_callback */ + +/** + * Get the well-knwon symbol represented by the given `symbol` enum value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return undefined value - if invalid well-known symbol was requested + * well-known symbol value - otherwise + */ +jerry_value_t +jerry_symbol (jerry_well_known_symbol_t symbol) /**< jerry_well_known_symbol_t enum value */ +{ + lit_magic_string_id_t id = (lit_magic_string_id_t) (LIT_GLOBAL_SYMBOL__FIRST + symbol); + + if (!LIT_IS_GLOBAL_SYMBOL (id)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_make_symbol_value (ecma_op_get_global_symbol (id)); +} /* jerry_get_well_known_symbol */ + +/** + * Returns the description internal property of a symbol. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return string or undefined value containing the symbol's description - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_symbol_description (const jerry_value_t symbol) /**< symbol value */ +{ + if (!ecma_is_value_symbol (symbol)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + /* Note: This operation cannot throw an error */ + return ecma_copy_value (ecma_get_symbol_description (ecma_get_symbol_from_value (symbol))); +} /* jerry_get_symbol_description */ + +/** + * Call the SymbolDescriptiveString ecma builtin operation on the symbol value. + * + * Note: + * returned value must be freed with jerry_value_free, when it is no longer needed. + * + * @return string value containing the symbol's descriptive string - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_symbol_descriptive_string (const jerry_value_t symbol) /**< symbol value */ +{ + if (!ecma_is_value_symbol (symbol)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + /* Note: This operation cannot throw an error */ + return ecma_get_symbol_descriptive_string (symbol); +} /* jerry_get_symbol_descriptive_string */ + +/** + * Get the number of uint64 digits of a BigInt value + * + * @return number of uint64 digits + */ +uint32_t +jerry_bigint_digit_count (const jerry_value_t value) /**< BigInt value */ +{ +#if JERRY_BUILTIN_BIGINT + if (!ecma_is_value_bigint (value)) + { + return 0; + } + + return ecma_bigint_get_size_in_digits (value); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return 0; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_bigint_digit_count */ + +/** + * Get the uint64 digits of a BigInt value (lowest digit first) + */ +void +jerry_bigint_to_digits (const jerry_value_t value, /**< BigInt value */ + uint64_t *digits_p, /**< [out] buffer for digits */ + uint32_t digit_count, /**< buffer size in digits */ + bool *sign_p) /**< [out] sign of BigInt */ +{ +#if JERRY_BUILTIN_BIGINT + if (!ecma_is_value_bigint (value)) + { + if (sign_p != NULL) + { + *sign_p = false; + } + memset (digits_p, 0, digit_count * sizeof (uint64_t)); + } + + ecma_bigint_get_digits_and_sign (value, digits_p, digit_count, sign_p); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + + if (sign_p != NULL) + { + *sign_p = false; + } + memset (digits_p, 0, digit_count * sizeof (uint64_t)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* jerry_bigint_to_digits */ + +/** + * Get the target object of a Proxy object + * + * @return type error - if proxy_value is not a Proxy object + * target object - otherwise + */ +jerry_value_t +jerry_proxy_target (const jerry_value_t proxy_value) /**< proxy value */ +{ +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_object (proxy_value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (proxy_value); + + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + ecma_proxy_object_t *proxy_object_p = (ecma_proxy_object_t *) object_p; + + if (!ecma_is_value_null (proxy_object_p->target)) + { + ecma_ref_object (ecma_get_object_from_value (proxy_object_p->target)); + } + return proxy_object_p->target; + } + } +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (proxy_value); +#endif /* JERRY_BUILTIN_PROXY */ + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY)); +} /* jerry_proxy_target */ + +/** + * Get the handler object of a Proxy object + * + * @return type error - if proxy_value is not a Proxy object + * handler object - otherwise + */ +jerry_value_t +jerry_proxy_handler (const jerry_value_t proxy_value) /**< proxy value */ +{ +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_object (proxy_value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (proxy_value); + + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + ecma_proxy_object_t *proxy_object_p = (ecma_proxy_object_t *) object_p; + + if (!ecma_is_value_null (proxy_object_p->handler)) + { + ecma_ref_object (ecma_get_object_from_value (proxy_object_p->handler)); + } + return proxy_object_p->handler; + } + } +#else /* !JERRY_BUILTIN_PROXY */ + JERRY_UNUSED (proxy_value); +#endif /* JERRY_BUILTIN_PROXY */ + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY)); +} /* jerry_proxy_handler */ + +/** + * Validate string buffer for the specified encoding + * + * @return true - if string is well-formed + * false - otherwise + */ +bool +jerry_validate_string (const jerry_char_t *buffer_p, /**< string buffer */ + jerry_size_t buffer_size, /**< buffer size */ + jerry_encoding_t encoding) /**< buffer encoding */ +{ + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + return lit_is_valid_cesu8_string (buffer_p, buffer_size); + } + case JERRY_ENCODING_UTF8: + { + return lit_is_valid_utf8_string (buffer_p, buffer_size, true); + } + default: + { + return false; + } + } +} /* jerry_validate_string */ + +/** + * Set the log level of the engine. + * + * Log messages with lower significance than the current log level will be ignored by `jerry_log`. + * + * @param level: requested log level + */ +void +jerry_log_set_level (jerry_log_level_t level) +{ + jerry_jrt_set_log_level (level); +} /* jerry_log_set_level */ + +/** + * Log buffer size + */ +#define JERRY_LOG_BUFFER_SIZE 64 + +/** + * Log a zero-terminated string message. + * + * @param str_p: message + */ +static void +jerry_log_string (const char *str_p) +{ + jerry_port_log (str_p); + +} /* jerry_log_string */ + +/** + * Log a fixed-size string message. + * + * @param str_p: message + * @param size: size + * @param buffer_p: buffer to use + */ +static void +jerry_log_string_fixed (const char *str_p, size_t size, char *buffer_p) +{ + const size_t batch_size = JERRY_LOG_BUFFER_SIZE - 1; + + while (size > batch_size) + { + memcpy (buffer_p, str_p, batch_size); + buffer_p[batch_size] = '\0'; + jerry_log_string (buffer_p); + + str_p += batch_size; + size -= batch_size; + } + + memcpy (buffer_p, str_p, size); + buffer_p[size] = '\0'; + jerry_log_string (buffer_p); +} /* jerry_log_string_fixed */ + +/** + * Format an unsigned number. + * + * @param num: number + * @param width: minimum width of the number + * @param padding: padding to be used when extending to minimum width + * @param radix: number radix + * @param buffer_p: buffer used to construct the number string + * + * @return formatted number as string + */ +static char * +jerry_format_unsigned (unsigned int num, uint8_t width, char padding, uint8_t radix, char *buffer_p) +{ + static const char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + char *cursor_p = buffer_p + JERRY_LOG_BUFFER_SIZE; + *(--cursor_p) = '\0'; + uint8_t count = 0; + + do + { + *(--cursor_p) = digits[num % radix]; + num /= radix; + count++; + } while (num > 0); + + while (count < width) + { + *(--cursor_p) = padding; + count++; + } + + return cursor_p; +} /* jerry_format_unsigned */ + +/** + * Format an integer number. + * + * @param num: number + * @param width: minimum width of the number + * @param padding: padding to be used when extending to minimum width + * @param buffer_p: buffer used to construct the number string + * + * @return formatted number as string + */ +static char * +jerry_format_int (int num, uint8_t width, char padding, char *buffer_p) +{ + if (num >= 0) + { + return jerry_format_unsigned ((unsigned) num, width, padding, 10, buffer_p); + } + + num = -num; + + if (padding == '0' && width > 0) + { + char *cursor_p = jerry_format_unsigned ((unsigned) num, --width, padding, 10, buffer_p); + *(--cursor_p) = '-'; + return cursor_p; + } + + char *cursor_p = jerry_format_unsigned ((unsigned) num, 0, ' ', 10, buffer_p); + *(--cursor_p) = '-'; + + char *indent_p = buffer_p + JERRY_LOG_BUFFER_SIZE - width - 1; + + while (cursor_p > indent_p) + { + *(--cursor_p) = ' '; + } + + return cursor_p; +} /* jerry_foramt_int */ + +/** + * Log a zero-terminated formatted message with the specified log level. + * + * Supported format specifiers: + * %s: zero-terminated string + * %c: character + * %u: unsigned integer + * %d: decimal integer + * %x: unsigned hexadecimal + * + * Width and padding sub-modifiers are also supported. + * + * @param format_p: format string + * @param level: message log level + */ +void +jerry_log (jerry_log_level_t level, const char *format_p, ...) +{ + if (level > jerry_jrt_get_log_level ()) + { + return; + } + + va_list vl; + char buffer_p[JERRY_LOG_BUFFER_SIZE]; + uint32_t buffer_index = 0; + const char *cursor_p = format_p; + va_start (vl, format_p); + + while (*cursor_p != '\0') + { + if (*cursor_p == '%' || buffer_index > JERRY_LOG_BUFFER_SIZE - 2) + { + buffer_p[buffer_index] = '\0'; + jerry_log_string (buffer_p); + buffer_index = 0; + } + + if (*cursor_p != '%') + { + buffer_p[buffer_index++] = *cursor_p++; + continue; + } + + ++cursor_p; + uint8_t width = 0; + size_t precision = 0; + char padding = ' '; + + if (*cursor_p == '0') + { + padding = '0'; + cursor_p++; + } + + if (lit_char_is_decimal_digit ((ecma_char_t) *cursor_p)) + { + width = (uint8_t) (*cursor_p - '0'); + cursor_p++; + } + else if (*cursor_p == '*') + { + width = (uint8_t) JERRY_MAX (va_arg (vl, int), 10); + cursor_p++; + } + else if (*cursor_p == '.' && *(cursor_p + 1) == '*') + { + precision = (size_t) va_arg (vl, int); + cursor_p += 2; + } + + if (*cursor_p == '\0') + { + buffer_p[buffer_index++] = '%'; + break; + } + + /* The buffer is always flushed before a substitution, and can be reused to for formatting. */ + switch (*cursor_p++) + { + case 's': + { + char *str_p = va_arg (vl, char *); + + if (precision == 0) + { + jerry_log_string (str_p); + break; + } + + jerry_log_string_fixed (str_p, precision, buffer_p); + break; + } + case 'c': + { + /* Arguments of types narrower than int are promoted to int for variadic functions */ + buffer_p[buffer_index++] = (char) va_arg (vl, int); + break; + } + case 'd': + { + jerry_log_string (jerry_format_int (va_arg (vl, int), width, padding, buffer_p)); + break; + } + case 'u': + { + jerry_log_string (jerry_format_unsigned (va_arg (vl, unsigned int), width, padding, 10, buffer_p)); + break; + } + case 'x': + { + jerry_log_string (jerry_format_unsigned (va_arg (vl, unsigned int), width, padding, 16, buffer_p)); + break; + } + default: + { + buffer_p[buffer_index++] = '%'; + break; + } + } + } + + if (buffer_index > 0) + { + buffer_p[buffer_index] = '\0'; + jerry_log_string (buffer_p); + } + + va_end (vl); +} /* jerry_log */ + +/** + * Allocate memory on the engine's heap. + * + * Note: + * This function may take away memory from the executed JavaScript code. + * If any other dynamic memory allocation API is available (e.g., libc + * malloc), it should be used instead. + * + * @return allocated memory on success + * NULL otherwise + */ +void * +jerry_heap_alloc (jerry_size_t size) /**< size of the memory block */ +{ + return jmem_heap_alloc_block_null_on_error (size); +} /* jerry_heap_alloc */ + +/** + * Free memory allocated on the engine's heap. + */ +void +jerry_heap_free (void *mem_p, /**< value returned by jerry_heap_alloc */ + jerry_size_t size) /**< same size as passed to jerry_heap_alloc */ +{ + jmem_heap_free_block (mem_p, size); +} /* jerry_heap_free */ + +/** + * When JERRY_VM_HALT is enabled, the callback passed to this function + * is periodically called with the user_p argument. If interval is greater + * than 1, the callback is only called at every interval ticks. + */ +void +jerry_halt_handler (uint32_t interval, /**< interval of the function call */ + jerry_halt_cb_t callback, /**< periodically called user function */ + void *user_p) /**< pointer passed to the function */ +{ +#if JERRY_VM_HALT + if (interval == 0) + { + interval = 1; + } + + JERRY_CONTEXT (vm_exec_stop_frequency) = interval; + JERRY_CONTEXT (vm_exec_stop_counter) = interval; + JERRY_CONTEXT (vm_exec_stop_cb) = callback; + JERRY_CONTEXT (vm_exec_stop_user_p) = user_p; +#else /* !JERRY_VM_HALT */ + JERRY_UNUSED (interval); + JERRY_UNUSED (callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_VM_HALT */ +} /* jerry_halt_handler */ + +/** + * Get backtrace. The backtrace is an array of strings where + * each string contains the position of the corresponding frame. + * The array length is zero if the backtrace is not available. + * + * @return array value + */ +jerry_value_t +jerry_backtrace (uint32_t max_depth) /**< depth limit of the backtrace */ +{ + return vm_get_backtrace (max_depth); +} /* jerry_backtrace */ + +/** + * Low-level function to capture each backtrace frame. + * The captured frame data is passed to a callback function. + */ +void +jerry_backtrace_capture (jerry_backtrace_cb_t callback, /**< callback function */ + void *user_p) /**< user pointer passed to the callback function */ +{ + jerry_frame_t frame; + vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); + + while (context_p != NULL) + { + frame.context_p = context_p; + frame.frame_type = JERRY_BACKTRACE_FRAME_JS; + + if (!callback (&frame, user_p)) + { + return; + } + + context_p = context_p->prev_context_p; + } +} /* jerry_backtrace */ + +/** + * Returns with the type of the backtrace frame. + * + * @return frame type listed in jerry_frame_type_t + */ +jerry_frame_type_t +jerry_frame_type (const jerry_frame_t *frame_p) /**< frame pointer */ +{ + return (jerry_frame_type_t) frame_p->frame_type; +} /* jerry_frame_type */ + +/** + * Initialize and return with the location private field of a backtrace frame. + * + * @return pointer to the location private field - if the location is available, + * NULL - otherwise + */ +const jerry_frame_location_t * +jerry_frame_location (jerry_frame_t *frame_p) /**< frame pointer */ +{ + JERRY_UNUSED (frame_p); + +#if JERRY_LINE_INFO + if (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS) + { + vm_frame_ctx_t *context_p = frame_p->context_p; + const ecma_compiled_code_t *bytecode_header_p = context_p->shared_p->bytecode_header_p; + + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO)) + { + return NULL; + } + + frame_p->location.source_name = ecma_get_source_name (bytecode_header_p); + + ecma_line_info_get (ecma_compiled_code_get_line_info (bytecode_header_p), + (uint32_t) (context_p->byte_code_p - context_p->byte_code_start_p), + &frame_p->location); + + return &frame_p->location; + } +#endif /* JERRY_LINE_INFO */ + + return NULL; +} /* jerry_frame_location */ + +/** + * Initialize and return with the called function private field of a backtrace frame. + * The backtrace frame is created for running the code bound to this function. + * + * @return pointer to the called function - if the function is available, + * NULL - otherwise + */ +const jerry_value_t * +jerry_frame_callee (jerry_frame_t *frame_p) /**< frame pointer */ +{ + if (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS) + { + vm_frame_ctx_t *context_p = frame_p->context_p; + + if (context_p->shared_p->function_object_p != NULL) + { + frame_p->function = ecma_make_object_value (context_p->shared_p->function_object_p); + return &frame_p->function; + } + } + + return NULL; +} /* jerry_frame_callee */ + +/** + * Initialize and return with the 'this' binding private field of a backtrace frame. + * The 'this' binding is a hidden value passed to the called function. As for arrow + * functions, the 'this' binding is assigned at function creation. + * + * @return pointer to the 'this' binding - if the binding is available, + * NULL - otherwise + */ +const jerry_value_t * +jerry_frame_this (jerry_frame_t *frame_p) /**< frame pointer */ +{ + if (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS) + { + frame_p->this_binding = frame_p->context_p->this_binding; + return &frame_p->this_binding; + } + + return NULL; +} /* jerry_frame_this */ + +/** + * Returns true, if the code bound to the backtrace frame is strict mode code. + * + * @return true - if strict mode code is bound to the frame, + * false - otherwise + */ +bool +jerry_frame_is_strict (jerry_frame_t *frame_p) /**< frame pointer */ +{ + return (frame_p->frame_type == JERRY_BACKTRACE_FRAME_JS + && (frame_p->context_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0); +} /* jerry_frame_is_strict */ + +/** + * Get the source name (usually a file name) of the currently executed script or the given function object + * + * Note: returned value must be freed with jerry_value_free, when it is no longer needed + * + * @return JS string constructed from + * - the currently executed function object's source name, if the given value is undefined + * - source name of the function object, if the given value is a function object + * - "", otherwise + */ +jerry_value_t +jerry_source_name (const jerry_value_t value) /**< jerry api value */ +{ +#if JERRY_SOURCE_NAME + if (ecma_is_value_undefined (value) && JERRY_CONTEXT (vm_top_context_p) != NULL) + { + return ecma_copy_value (ecma_get_source_name (JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p)); + } + + ecma_value_t script_value = ecma_script_get_from_value (value); + + if (script_value == JMEM_CP_NULL) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); + } + + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return ecma_copy_value (script_p->source_name); +#else /* !JERRY_SOURCE_NAME */ + JERRY_UNUSED (value); + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); +#endif /* JERRY_SOURCE_NAME */ +} /* jerry_source_name */ + +/** + * Returns the user value assigned to a script / module / function. + * + * Note: + * This value is usually set by the parser when + * the JERRY_PARSE_HAS_USER_VALUE flag is passed. + * + * @return user value + */ +jerry_value_t +jerry_source_user_value (const jerry_value_t value) /**< jerry api value */ +{ + ecma_value_t script_value = ecma_script_get_from_value (value); + + if (script_value == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_copy_value (CBC_SCRIPT_GET_USER_VALUE (script_p)); +} /* jerry_source_user_value */ + +/** + * Checks whether an ECMAScript code is compiled by eval + * like (eval, new Function, jerry_eval, etc.) command. + * + * @return true, if code is compiled by eval like command + * false, otherwise + */ +bool +jerry_function_is_dynamic (const jerry_value_t value) /**< jerry api value */ +{ + ecma_value_t script_value = ecma_script_get_from_value (value); + + if (script_value == JMEM_CP_NULL) + { + return false; + } + + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return (script_p->refs_and_type & CBC_SCRIPT_IS_EVAL_CODE) != 0; +} /* jerry_function_is_dynamic */ + +/** + * Returns a newly created source info structure corresponding to the passed script/module/function. + * + * @return a newly created source info, if at least one field is available, NULL otherwise + */ +jerry_source_info_t * +jerry_source_info (const jerry_value_t value) /**< jerry api value */ +{ +#if JERRY_FUNCTION_TO_STRING + if (!ecma_is_value_object (value)) + { + return NULL; + } + + jerry_source_info_t source_info; + + source_info.enabled_fields = 0; + source_info.source_code = ECMA_VALUE_UNDEFINED; + source_info.function_arguments = ECMA_VALUE_UNDEFINED; + source_info.source_range_start = 0; + source_info.source_range_length = 0; + + ecma_object_t *object_p = ecma_get_object_from_value (value); + cbc_script_t *script_p = NULL; + + while (true) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + const ecma_compiled_code_t *bytecode_p = NULL; + + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_SCRIPT) + { + bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + } +#if JERRY_MODULE_SYSTEM + else if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_MODULE) + { + ecma_module_t *module_p = (ecma_module_t *) object_p; + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)) + { + bytecode_p = module_p->u.compiled_code_p; + } + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (bytecode_p == NULL) + { + return NULL; + } + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + const ecma_compiled_code_t *bytecode_p; + bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_p); + uint8_t extended_info = *extended_info_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + ecma_extended_info_decode_vlq (&extended_info_p); + } + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS) + { + ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + + ecma_ref_ecma_string (ecma_get_string_from_value (function_arguments)); + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_SOURCE_CODE; + source_info.source_code = function_arguments; + script_p = NULL; + } + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_SOURCE_RANGE; + source_info.source_range_start = ecma_extended_info_decode_vlq (&extended_info_p); + source_info.source_range_length = ecma_extended_info_decode_vlq (&extended_info_p); + } + + JERRY_ASSERT (script_p != NULL || (source_info.enabled_fields & JERRY_SOURCE_INFO_HAS_SOURCE_CODE)); + + if (source_info.enabled_fields == 0 && (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)) + { + ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + + ecma_ref_ecma_string (ecma_get_string_from_value (function_arguments)); + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_FUNCTION_ARGUMENTS; + source_info.function_arguments = function_arguments; + } + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + object_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_object_p->u.bound_function.target_function); + continue; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_value_t script_value = ((ecma_extended_object_t *) object_p)->u.constructor_function.script_value; + script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + break; + } + default: + { + return NULL; + } + } + + break; + } + + jerry_source_info_t *source_info_p = jmem_heap_alloc_block_null_on_error (sizeof (jerry_source_info_t)); + + if (source_info_p == NULL) + { + return NULL; + } + + if (script_p != NULL) + { + ecma_ref_ecma_string (ecma_get_string_from_value (script_p->source_code)); + + source_info.enabled_fields |= JERRY_SOURCE_INFO_HAS_SOURCE_CODE; + source_info.source_code = script_p->source_code; + } + + JERRY_ASSERT (source_info.enabled_fields != 0); + + *source_info_p = source_info; + return source_info_p; +#else /* !JERRY_FUNCTION_TO_STRING */ + JERRY_UNUSED (value); + return NULL; +#endif /* JERRY_FUNCTION_TO_STRING */ +} /* jerry_source_info */ + +/** + * Frees the the source info structure returned by jerry_source_info. + */ +void +jerry_source_info_free (jerry_source_info_t *source_info_p) /**< source info block */ +{ +#if JERRY_FUNCTION_TO_STRING + if (source_info_p != NULL) + { + ecma_free_value (source_info_p->source_code); + ecma_free_value (source_info_p->function_arguments); + jmem_heap_free_block (source_info_p, sizeof (jerry_source_info_t)); + } +#else /* !JERRY_FUNCTION_TO_STRING */ + JERRY_UNUSED (source_info_p); +#endif /* JERRY_FUNCTION_TO_STRING */ +} /* jerry_source_info_free */ + +/** + * Replaces the currently active realm with another realm. + * + * The replacement should be temporary, and the original realm must be + * restored after the tasks are completed. During the replacement, the + * realm must be referenced by the application (i.e. the gc must not + * reclaim it). This is also true to the returned previously active + * realm, so there is no need to free the value after the restoration. + * + * @return previous realm value - if the passed value is a realm + * exception - otherwise + */ +jerry_value_t +jerry_set_realm (jerry_value_t realm_value) /**< jerry api value */ +{ +#if JERRY_BUILTIN_REALMS + if (ecma_is_value_object (realm_value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (realm_value); + + if (ecma_builtin_is_global (object_p)) + { + ecma_global_object_t *previous_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) object_p; + return ecma_make_object_value ((ecma_object_t *) previous_global_object_p); + } + } + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM)); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_UNUSED (realm_value); + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_REALM_IS_NOT_AVAILABLE)); +#endif /* JERRY_BUILTIN_REALMS */ +} /* jerry_set_realm */ + +/** + * Gets the 'this' binding of a realm + * + * @return type error - if realm_value is not a realm + * this value - otherwise + */ +jerry_value_t +jerry_realm_this (jerry_value_t realm) /**< realm value */ +{ +#if JERRY_BUILTIN_REALMS + if (ecma_is_value_object (realm)) + { + ecma_object_t *object_p = ecma_get_object_from_value (realm); + + if (ecma_builtin_is_global (object_p)) + { + ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p; + + ecma_ref_object (ecma_get_object_from_value (global_object_p->this_binding)); + return global_object_p->this_binding; + } + } + +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *global_object_p = ecma_builtin_get_global (); + + if (realm == ecma_make_object_value (global_object_p)) + { + ecma_ref_object (global_object_p); + return realm; + } +#endif /* JERRY_BUILTIN_REALMS */ + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM)); +} /* jerry_realm_this */ + +/** + * Sets the 'this' binding of a realm + * + * This function must be called before executing any script on the realm. + * Otherwise the operation is undefined. + * + * @return type error - if realm_value is not a realm or this_value is not object + * true - otherwise + */ +jerry_value_t +jerry_realm_set_this (jerry_value_t realm, /**< realm value */ + jerry_value_t this_value) /**< this value */ +{ +#if JERRY_BUILTIN_REALMS + if (!ecma_is_value_object (this_value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_SECOND_ARGUMENT_MUST_BE_AN_OBJECT)); + } + + if (ecma_is_value_object (realm)) + { + ecma_object_t *object_p = ecma_get_object_from_value (realm); + + if (ecma_builtin_is_global (object_p)) + { + ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p; + global_object_p->this_binding = this_value; + + ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL, ecma_get_object_from_value (this_value)); + + ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p); + global_object_p->global_scope_cp = global_object_p->global_env_cp; + + ecma_deref_object (global_lex_env_p); + return ECMA_VALUE_TRUE; + } + } + + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_FIRST_ARGUMENT_IS_NOT_A_REALM)); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_UNUSED (realm); + JERRY_UNUSED (this_value); + return jerry_throw_sz (JERRY_ERROR_REFERENCE, ecma_get_error_msg (ECMA_ERR_REALM_IS_NOT_AVAILABLE)); +#endif /* JERRY_BUILTIN_REALMS */ +} /* jerry_realm_set_this */ + +/** + * Check if the given value is an ArrayBuffer object. + * + * @return true - if it is an ArrayBuffer object + * false - otherwise + */ +bool +jerry_value_is_arraybuffer (const jerry_value_t value) /**< value to check if it is an ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + return ecma_is_arraybuffer (value); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_value_is_arraybuffer */ + +/** + * Creates an ArrayBuffer object with the given length (size). + * + * Notes: + * * the length is specified in bytes. + * * returned value must be freed with jerry_value_free, when it is no longer needed. + * * if the typed arrays are disabled this will return a TypeError. + * + * @return value of the constructed ArrayBuffer object + */ +jerry_value_t +jerry_arraybuffer (const jerry_length_t size) /**< size of the backing store allocated + * for the array buffer in bytes */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + return jerry_return (ecma_make_object_value (ecma_arraybuffer_new_object (size))); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (size); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer */ + +/** + * Creates an ArrayBuffer object with user specified buffer. + * + * Notes: + * * the size is specified in bytes. + * * the buffer passed should be at least the specified bytes big. + * * if the typed arrays are disabled this will return a TypeError. + * * if the size is zero or buffer_p is a null pointer this will return an empty ArrayBuffer. + * + * @return value of the newly constructed array buffer object + */ +jerry_value_t +jerry_arraybuffer_external (uint8_t *buffer_p, /**< the backing store used by the array buffer object */ + jerry_length_t size, /**< size of the buffer in bytes */ + void *user_p) /**< user pointer assigned to the array buffer object */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + ecma_object_t *arraybuffer_p; + + if (JERRY_UNLIKELY (size == 0)) + { + arraybuffer_p = ecma_arraybuffer_new_object (0); + } + else + { + arraybuffer_p = ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_ARRAY_BUFFER, size); + + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p; + arraybuffer_pointer_p->arraybuffer_user_p = user_p; + + if (buffer_p != NULL) + { + arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + arraybuffer_pointer_p->buffer_p = buffer_p; + } + } + + return jerry_return (ecma_make_object_value (arraybuffer_p)); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (size); + JERRY_UNUSED (buffer_p); + JERRY_UNUSED (user_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_external */ + +/** + * Check if the given value is a SharedArrayBuffer object. + * + * @return true - if it is a SharedArrayBuffer object + * false - otherwise + */ +bool +jerry_value_is_shared_arraybuffer (const jerry_value_t value) /**< value to check if it is a SharedArrayBuffer */ +{ + return ecma_is_shared_arraybuffer (value); +} /* jerry_value_is_shared_arraybuffer */ + +/** + * Creates a SharedArrayBuffer object with the given length (size). + * + * Notes: + * * the length is specified in bytes. + * * returned value must be freed with jerry_value_free, when it is no longer needed. + * * if the typed arrays are disabled this will return a TypeError. + * + * @return value of the constructed SharedArrayBuffer object + */ +jerry_value_t +jerry_shared_arraybuffer (jerry_length_t size) /**< size of the backing store allocated + * for the shared array buffer in bytes */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + return jerry_return (ecma_make_object_value (ecma_shared_arraybuffer_new_object (size))); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (size); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* jerry_shared_arraybuffer */ + +/** + * Creates a SharedArrayBuffer object with user specified buffer. + * + * Notes: + * * the size is specified in bytes. + * * the buffer passed should be at least the specified bytes big. + * * if the typed arrays are disabled this will return a TypeError. + * * if the size is zero or buffer_p is a null pointer this will return an empty SharedArrayBuffer. + * + * @return value of the newly constructed shared array buffer object + */ +jerry_value_t +jerry_shared_arraybuffer_external (uint8_t *buffer_p, /**< the backing store used by the + * shared array buffer object */ + jerry_length_t size, /**< size of the buffer in bytes */ + void *user_p) /**< user pointer assigned to the + * shared array buffer object */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + ecma_object_t *shared_arraybuffer_p; + + if (JERRY_UNLIKELY (size == 0)) + { + shared_arraybuffer_p = ecma_shared_arraybuffer_new_object (0); + } + else + { + shared_arraybuffer_p = ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, size); + + ecma_arraybuffer_pointer_t *shared_arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) shared_arraybuffer_p; + shared_arraybuffer_pointer_p->arraybuffer_user_p = user_p; + + if (buffer_p != NULL) + { + shared_arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + shared_arraybuffer_pointer_p->buffer_p = buffer_p; + } + } + + return ecma_make_object_value (shared_arraybuffer_p); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (size); + JERRY_UNUSED (buffer_p); + JERRY_UNUSED (user_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* jerry_shared_arraybuffer_external */ + +#if JERRY_BUILTIN_TYPEDARRAY + +/** + * Allocate a backing store for an array buffer, ignores allocation fails. + * + * @return true on success, + * false otherwise + */ +static bool +jerry_arraybuffer_allocate_buffer_no_throw (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */ +{ + JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)); + + if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED) + { + return false; + } + + return ecma_arraybuffer_allocate_buffer (arraybuffer_p) != ECMA_VALUE_ERROR; +} /* jerry_arraybuffer_allocate_buffer_no_throw */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** + * Copy bytes into the ArrayBuffer or SharedArrayBuffer from a buffer. + * + * Note: + * * returns 0, if the passed object is not an ArrayBuffer or SharedArrayBuffer + * + * @return number of bytes copied into the ArrayBuffer or SharedArrayBuffer. + */ +jerry_length_t +jerry_arraybuffer_write (jerry_value_t value, /**< target ArrayBuffer or SharedArrayBuffer */ + jerry_length_t offset, /**< start offset of the ArrayBuffer */ + const uint8_t *buf_p, /**< buffer to copy from */ + jerry_length_t buf_size) /**< number of bytes to copy from the buffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!(ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value))) + { + return 0; + } + + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED) + && !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p)) + { + return 0; + } + + jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p); + + if (offset >= length) + { + return 0; + } + + jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size); + + if (copy_count > 0) + { + lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p); + + memcpy ((void *) (buffer_p + offset), (void *) buf_p, copy_count); + } + + return copy_count; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + JERRY_UNUSED (offset); + JERRY_UNUSED (buf_p); + JERRY_UNUSED (buf_size); + return 0; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_write */ + +/** + * Copy bytes from a buffer into an ArrayBuffer or SharedArrayBuffer. + * + * Note: + * * if the object passed is not an ArrayBuffer or SharedArrayBuffer will return 0. + * + * @return number of bytes read from the ArrayBuffer. + */ +jerry_length_t +jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer or SharedArrayBuffer to read from */ + jerry_length_t offset, /**< start offset of the ArrayBuffer or SharedArrayBuffer */ + uint8_t *buf_p, /**< destination buffer to copy to */ + jerry_length_t buf_size) /**< number of bytes to copy into the buffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!(ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value))) + { + return 0; + } + + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED) + && !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p)) + { + return 0; + } + + jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p); + + if (offset >= length) + { + return 0; + } + + jerry_length_t copy_count = JERRY_MIN (length - offset, buf_size); + + if (copy_count > 0) + { + lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p); + + memcpy ((void *) buf_p, (void *) (buffer_p + offset), copy_count); + } + + return copy_count; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + JERRY_UNUSED (offset); + JERRY_UNUSED (buf_p); + JERRY_UNUSED (buf_size); + return 0; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_read */ + +/** + * Get the length (size) of the ArrayBuffer or SharedArrayBuffer in bytes. + * + * Note: + * This is the 'byteLength' property of an ArrayBuffer or SharedArrayBuffer. + * + * @return the length of the ArrayBuffer in bytes. + */ +jerry_length_t +jerry_arraybuffer_size (const jerry_value_t value) /**< ArrayBuffer or SharedArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value)) + { + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value); + return ecma_arraybuffer_get_length (arraybuffer_p); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + return 0; +} /* jerry_arraybuffer_size */ + +/** + * Get a pointer for the start of the ArrayBuffer. + * + * Note: + * * This is a high-risk operation as the bounds are not checked + * when accessing the pointer elements. + * + * @return pointer to the back-buffer of the ArrayBuffer. + * pointer is NULL if: + * - the parameter is not an ArrayBuffer + * - an external ArrayBuffer has been detached + */ +uint8_t * +jerry_arraybuffer_data (const jerry_value_t array_buffer) /**< Array Buffer to use */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!(ecma_is_arraybuffer (array_buffer) || ecma_is_shared_arraybuffer (array_buffer))) + { + return NULL; + } + + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (array_buffer); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED) + && !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p)) + { + return NULL; + } + + return (uint8_t *) ecma_arraybuffer_get_buffer (arraybuffer_p); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (array_buffer); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + return NULL; +} /* jerry_arraybuffer_data */ + +/** + * Get if the ArrayBuffer is detachable. + * + * @return boolean value - if success + * value marked with error flag - otherwise + */ +bool +jerry_arraybuffer_is_detachable (const jerry_value_t value) /**< ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_arraybuffer (value)) + { + ecma_object_t *buffer_p = ecma_get_object_from_value (value); + return !ecma_arraybuffer_is_detached (buffer_p); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + return false; +} /* jerry_arraybuffer_is_detachable */ + +/** + * Detach the underlying data block from ArrayBuffer and set its bytelength to 0. + * + * Note: if the ArrayBuffer has a separate data buffer, the free callback set by + * jerry_arraybuffer_set_allocation_callbacks is called for this buffer + * + * @return null value - if success + * value marked with error flag - otherwise + */ +jerry_value_t +jerry_arraybuffer_detach (jerry_value_t value) /**< ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_arraybuffer (value)) + { + ecma_object_t *buffer_p = ecma_get_object_from_value (value); + if (ecma_arraybuffer_detach (buffer_p)) + { + return ECMA_VALUE_NULL; + } + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARRAY_BUFFER_DETACHED)); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_EXPECTED_AN_ARRAYBUFFER)); +} /* jerry_arraybuffer_detach */ + +/** + * Checks whether a buffer is currently allocated for an array buffer or typed array. + * + * @return true, if a buffer is allocated for an array buffer or typed array + * false, otherwise + */ +bool +jerry_arraybuffer_has_buffer (const jerry_value_t value) /**< array buffer or typed array value */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!ecma_is_value_object (value)) + { + return false; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + + if (ecma_object_is_typedarray (object_p)) + { + object_p = ecma_typedarray_get_arraybuffer (object_p); + } + else if (!(ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p))) + { + return false; + } + + return (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED) != 0; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_has_buffer */ + +/** + * Array buffers which size is less or equal than the limit passed to this function are allocated in + * a single memory block. The allocator callbacks set by jerry_arraybuffer_set_allocation_callbacks + * are not called for these array buffers. The default limit is 256 bytes. + */ +void +jerry_arraybuffer_heap_allocation_limit (jerry_length_t allocation_limit) /**< maximum size of + * compact allocation */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_CONTEXT (arraybuffer_compact_allocation_limit) = allocation_limit; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (allocation_limit); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_heap_allocation_limit */ + +/** + * Set callbacks for allocating and freeing backing stores for array buffer objects. + */ +void +jerry_arraybuffer_allocator (jerry_arraybuffer_allocate_cb_t allocate_callback, /**< callback for allocating + * array buffer memory */ + jerry_arraybuffer_free_cb_t free_callback, /**< callback for freeing + * array buffer memory */ + void *user_p) /**< user pointer passed to the callbacks */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_CONTEXT (arraybuffer_allocate_callback) = allocate_callback; + JERRY_CONTEXT (arraybuffer_free_callback) = free_callback; + JERRY_CONTEXT (arraybuffer_allocate_callback_user_p) = user_p; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (allocate_callback); + JERRY_UNUSED (free_callback); + JERRY_UNUSED (user_p); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_arraybuffer_allocator */ + +/** + * DataView related functions + */ + +/** + * Creates a DataView object with the given ArrayBuffer, ByteOffset and ByteLength arguments. + * + * Notes: + * * returned value must be freed with jerry_value_free, when it is no longer needed. + * * if the DataView bulitin is disabled this will return a TypeError. + * + * @return value of the constructed DataView object - if success + * created error - otherwise + */ +jerry_value_t +jerry_dataview (const jerry_value_t array_buffer, /**< arraybuffer to create DataView from */ + jerry_length_t byte_offset, /**< offset in bytes, to the first byte in the buffer */ + jerry_length_t byte_length) /**< number of elements in the byte array */ +{ +#if JERRY_BUILTIN_DATAVIEW + if (ecma_is_value_exception (array_buffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_value_t arguments_p[3] = { array_buffer, + ecma_make_uint32_value (byte_offset), + ecma_make_uint32_value (byte_length) }; + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + if (old_new_target_p == NULL) + { + JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ECMA_BUILTIN_ID_DATAVIEW); + } + + ecma_value_t dataview_value = ecma_op_dataview_create (arguments_p, 3); + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + return jerry_return (dataview_value); +#else /* !JERRY_BUILTIN_DATAVIEW */ + JERRY_UNUSED (array_buffer); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (byte_length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_DATA_VIEW_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_DATAVIEW */ +} /* jerry_dataview */ + +/** + * Check if the given value is a DataView object. + * + * @return true - if it is a DataView object + * false - otherwise + */ +bool +jerry_value_is_dataview (const jerry_value_t value) /**< value to check if it is a DataView object */ +{ +#if JERRY_BUILTIN_DATAVIEW + return ecma_is_dataview (value); +#else /* !JERRY_BUILTIN_DATAVIEW */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_DATAVIEW */ +} /* jerry_value_is_dataview */ + +/** + * Get the underlying ArrayBuffer from a DataView. + * + * Additionally the byteLength and byteOffset properties are also returned + * which were specified when the DataView was created. + * + * Note: + * the returned value must be freed with a jerry_value_free call + * + * @return ArrayBuffer of a DataView + * TypeError if the object is not a DataView. + */ +jerry_value_t +jerry_dataview_buffer (const jerry_value_t value, /**< DataView to get the arraybuffer from */ + jerry_length_t *byte_offset, /**< [out] byteOffset property */ + jerry_length_t *byte_length) /**< [out] byteLength property */ +{ +#if JERRY_BUILTIN_DATAVIEW + if (ecma_is_value_exception (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + + ecma_dataview_object_t *dataview_p = ecma_op_dataview_get_object (value); + + if (JERRY_UNLIKELY (dataview_p == NULL)) + { + return ecma_create_exception_from_context (); + } + + if (byte_offset != NULL) + { + *byte_offset = dataview_p->byte_offset; + } + + if (byte_length != NULL) + { + *byte_length = dataview_p->header.u.cls.u3.length; + } + + ecma_object_t *arraybuffer_p = dataview_p->buffer_p; + ecma_ref_object (arraybuffer_p); + + return ecma_make_object_value (arraybuffer_p); +#else /* !JERRY_BUILTIN_DATAVIEW */ + JERRY_UNUSED (value); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (byte_length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_DATA_VIEW_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_DATAVIEW */ +} /* jerry_dataview_buffer */ + +/** + * TypedArray related functions + */ + +/** + * Check if the given value is a TypedArray object. + * + * @return true - if it is a TypedArray object + * false - otherwise + */ +bool +jerry_value_is_typedarray (const jerry_value_t value) /**< value to check if it is a TypedArray */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + return ecma_is_typedarray (value); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_value_is_typedarray */ + +#if JERRY_BUILTIN_TYPEDARRAY +/** + * TypedArray mapping type + */ +typedef struct +{ + jerry_typedarray_type_t api_type; /**< api type */ + ecma_builtin_id_t prototype_id; /**< prototype ID */ + ecma_typedarray_type_t id; /**< typedArray ID */ + uint8_t element_size_shift; /**< element size shift */ +} jerry_typedarray_mapping_t; + +/** + * List of TypedArray mappings + */ +static jerry_typedarray_mapping_t jerry_typedarray_mappings[] = { +#define TYPEDARRAY_ENTRY(NAME, LIT_NAME, SIZE_SHIFT) \ + { \ + JERRY_TYPEDARRAY_##NAME, ECMA_BUILTIN_ID_##NAME##ARRAY_PROTOTYPE, ECMA_##LIT_NAME##_ARRAY, SIZE_SHIFT \ + } + + TYPEDARRAY_ENTRY (UINT8, UINT8, 0), TYPEDARRAY_ENTRY (UINT8CLAMPED, UINT8_CLAMPED, 0), + TYPEDARRAY_ENTRY (INT8, INT8, 0), TYPEDARRAY_ENTRY (UINT16, UINT16, 1), + TYPEDARRAY_ENTRY (INT16, INT16, 1), TYPEDARRAY_ENTRY (UINT32, UINT32, 2), + TYPEDARRAY_ENTRY (INT32, INT32, 2), TYPEDARRAY_ENTRY (FLOAT32, FLOAT32, 2), +#if JERRY_NUMBER_TYPE_FLOAT64 + TYPEDARRAY_ENTRY (FLOAT64, FLOAT64, 3), +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + TYPEDARRAY_ENTRY (BIGINT64, BIGINT64, 3), TYPEDARRAY_ENTRY (BIGUINT64, BIGUINT64, 3), +#endif /* JERRY_BUILTIN_BIGINT */ +#undef TYPEDARRAY_ENTRY +}; + +/** + * Helper function to get the TypedArray prototype, typedArray id, and element size shift + * information. + * + * @return true - if the TypedArray information was found + * false - if there is no such TypedArray type + */ +static bool +jerry_typedarray_find_by_type (jerry_typedarray_type_t type_name, /**< type of the TypedArray */ + ecma_builtin_id_t *prototype_id, /**< [out] found prototype object id */ + ecma_typedarray_type_t *id, /**< [out] found typedArray id */ + uint8_t *element_size_shift) /**< [out] found element size shift value */ +{ + JERRY_ASSERT (prototype_id != NULL); + JERRY_ASSERT (id != NULL); + JERRY_ASSERT (element_size_shift != NULL); + + for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++) + { + if (type_name == jerry_typedarray_mappings[i].api_type) + { + *prototype_id = jerry_typedarray_mappings[i].prototype_id; + *id = jerry_typedarray_mappings[i].id; + *element_size_shift = jerry_typedarray_mappings[i].element_size_shift; + return true; + } + } + + return false; +} /* jerry_typedarray_find_by_type */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** + * Create a TypedArray object with a given type and length. + * + * Notes: + * * returns TypeError if an incorrect type (type_name) is specified. + * * byteOffset property will be set to 0. + * * byteLength property will be a multiple of the length parameter (based on the type). + * + * @return - new TypedArray object + */ +jerry_value_t +jerry_typedarray (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */ + jerry_length_t length) /**< element count of the new TypedArray */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + ecma_builtin_id_t prototype_id = (ecma_builtin_id_t) 0; + ecma_typedarray_type_t id = (ecma_typedarray_type_t) 0; + uint8_t element_size_shift = 0; + + if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &id, &element_size_shift)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY)); + } + + ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id); + + ecma_value_t array_value = + ecma_typedarray_create_object_with_length (length, NULL, prototype_obj_p, element_size_shift, id); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value)); + + return array_value; +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (type_name); + JERRY_UNUSED (length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray */ + +/** + * Create a TypedArray object using the given arraybuffer and size information. + * + * Notes: + * * returns TypeError if an incorrect type (type_name) is specified. + * * this is the 'new %TypedArray%(arraybuffer, byteOffset, length)' equivalent call. + * + * @return - new TypedArray object + */ +jerry_value_t +jerry_typedarray_with_buffer_span (jerry_typedarray_type_t type, /**< type of TypedArray to create */ + const jerry_value_t arraybuffer, /**< ArrayBuffer to use */ + jerry_length_t byte_offset, /**< offset for the ArrayBuffer */ + jerry_length_t length) /**< number of elements to use from ArrayBuffer */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_value_exception (arraybuffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + ecma_builtin_id_t prototype_id = (ecma_builtin_id_t) 0; + ecma_typedarray_type_t id = (ecma_typedarray_type_t) 0; + uint8_t element_size_shift = 0; + + if (!jerry_typedarray_find_by_type (type, &prototype_id, &id, &element_size_shift)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY)); + } + + if (!ecma_is_arraybuffer (arraybuffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER)); + } + + ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id); + ecma_value_t arguments_p[3] = { arraybuffer, ecma_make_uint32_value (byte_offset), ecma_make_uint32_value (length) }; + + ecma_value_t array_value = ecma_op_create_typedarray (arguments_p, 3, prototype_obj_p, element_size_shift, id); + ecma_free_value (arguments_p[1]); + ecma_free_value (arguments_p[2]); + + return jerry_return (array_value); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (type); + JERRY_UNUSED (arraybuffer); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (length); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray_with_buffer_span */ + +/** + * Create a TypedArray object using the given arraybuffer and size information. + * + * Notes: + * * returns TypeError if an incorrect type (type_name) is specified. + * * this is the 'new %TypedArray%(arraybuffer)' equivalent call. + * + * @return - new TypedArray object + */ +jerry_value_t +jerry_typedarray_with_buffer (jerry_typedarray_type_t type, /**< type of TypedArray to create */ + const jerry_value_t arraybuffer) /**< ArrayBuffer to use */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_value_exception (arraybuffer)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + + jerry_length_t byte_length = jerry_arraybuffer_size (arraybuffer); + return jerry_typedarray_with_buffer_span (type, arraybuffer, 0, byte_length); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (type); + JERRY_UNUSED (arraybuffer); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray_with_buffer */ + +/** + * Get the type of the TypedArray. + * + * @return - type of the TypedArray + * - JERRY_TYPEDARRAY_INVALID if the argument is not a TypedArray + */ +jerry_typedarray_type_t +jerry_typedarray_type (const jerry_value_t value) /**< object to get the TypedArray type */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!ecma_is_typedarray (value)) + { + return JERRY_TYPEDARRAY_INVALID; + } + + ecma_object_t *array_p = ecma_get_object_from_value (value); + ecma_typedarray_type_t class_type = ecma_get_typedarray_id (array_p); + + for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++) + { + if (class_type == jerry_typedarray_mappings[i].id) + { + return jerry_typedarray_mappings[i].api_type; + } + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + return JERRY_TYPEDARRAY_INVALID; +} /* jerry_typedarray_type */ + +/** + * Get the element count of the TypedArray. + * + * @return length of the TypedArray. + */ +jerry_length_t +jerry_typedarray_length (const jerry_value_t value) /**< TypedArray to query */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (ecma_is_typedarray (value)) + { + ecma_object_t *array_p = ecma_get_object_from_value (value); + return ecma_typedarray_get_length (array_p); + } +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + return 0; +} /* jerry_typedarray_length */ + +/** + * Get the underlying ArrayBuffer from a TypedArray. + * + * Additionally the byteLength and byteOffset properties are also returned + * which were specified when the TypedArray was created. + * + * Note: + * the returned value must be freed with a jerry_value_free call + * + * @return ArrayBuffer of a TypedArray + * TypeError if the object is not a TypedArray. + */ +jerry_value_t +jerry_typedarray_buffer (const jerry_value_t value, /**< TypedArray to get the arraybuffer from */ + jerry_length_t *byte_offset, /**< [out] byteOffset property */ + jerry_length_t *byte_length) /**< [out] byteLength property */ +{ +#if JERRY_BUILTIN_TYPEDARRAY + if (!ecma_is_typedarray (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_OBJECT_IS_NOT_A_TYPEDARRAY)); + } + + ecma_object_t *array_p = ecma_get_object_from_value (value); + uint8_t shift = ecma_typedarray_get_element_size_shift (array_p); + + if (byte_length != NULL) + { + *byte_length = (jerry_length_t) (ecma_typedarray_get_length (array_p) << shift); + } + + if (byte_offset != NULL) + { + *byte_offset = (jerry_length_t) ecma_typedarray_get_offset (array_p); + } + + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_p); + ecma_ref_object (arraybuffer_p); + return jerry_return (ecma_make_object_value (arraybuffer_p)); +#else /* !JERRY_BUILTIN_TYPEDARRAY */ + JERRY_UNUSED (value); + JERRY_UNUSED (byte_length); + JERRY_UNUSED (byte_offset); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* jerry_typedarray_buffer */ + + +/** + * Create a container type specified in jerry_container_type_t. + * The container can be created with a list of arguments, which will be passed to the container constructor to be + * inserted to the container. + * + * Note: + * The returned value must be freed with jerry_value_free + * @return jerry_value_t representing a container with the given type. + */ +jerry_value_t +jerry_container (jerry_container_type_t container_type, /**< Type of the container */ + const jerry_value_t *arguments_list_p, /**< arguments list */ + jerry_length_t arguments_list_len) /**< Length of arguments list */ +{ +#if JERRY_BUILTIN_CONTAINER + for (jerry_length_t i = 0; i < arguments_list_len; i++) + { + if (ecma_is_value_exception (arguments_list_p[i])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_VALUE_MSG)); + } + } + + lit_magic_string_id_t lit_id; + ecma_builtin_id_t proto_id; + ecma_builtin_id_t ctor_id; + + switch (container_type) + { + case JERRY_CONTAINER_TYPE_MAP: + { + lit_id = LIT_MAGIC_STRING_MAP_UL; + proto_id = ECMA_BUILTIN_ID_MAP_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_MAP; + break; + } + case JERRY_CONTAINER_TYPE_SET: + { + lit_id = LIT_MAGIC_STRING_SET_UL; + proto_id = ECMA_BUILTIN_ID_SET_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_SET; + break; + } + case JERRY_CONTAINER_TYPE_WEAKMAP: + { + lit_id = LIT_MAGIC_STRING_WEAKMAP_UL; + proto_id = ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_WEAKMAP; + break; + } + case JERRY_CONTAINER_TYPE_WEAKSET: + { + lit_id = LIT_MAGIC_STRING_WEAKSET_UL; + proto_id = ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE; + ctor_id = ECMA_BUILTIN_ID_WEAKSET; + break; + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INVALID_CONTAINER_TYPE)); + } + } + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (old_new_target_p == NULL) + { + JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ctor_id); + } + + ecma_value_t container_value = ecma_op_container_create (arguments_list_p, arguments_list_len, lit_id, proto_id); + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + return jerry_return (container_value); +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (arguments_list_p); + JERRY_UNUSED (arguments_list_len); + JERRY_UNUSED (container_type); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_CONTAINER */ +} /* jerry_container */ + +/** + * Get the type of the given container object. + * + * @return Corresponding type to the given container object. + */ +jerry_container_type_t +jerry_container_type (const jerry_value_t value) /**< the container object */ +{ +#if JERRY_BUILTIN_CONTAINER + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_CONTAINER)) + { + switch (((ecma_extended_object_t *) obj_p)->u.cls.u2.container_id) + { + case LIT_MAGIC_STRING_MAP_UL: + { + return JERRY_CONTAINER_TYPE_MAP; + } + case LIT_MAGIC_STRING_SET_UL: + { + return JERRY_CONTAINER_TYPE_SET; + } + case LIT_MAGIC_STRING_WEAKMAP_UL: + { + return JERRY_CONTAINER_TYPE_WEAKMAP; + } + case LIT_MAGIC_STRING_WEAKSET_UL: + { + return JERRY_CONTAINER_TYPE_WEAKSET; + } + default: + { + return JERRY_CONTAINER_TYPE_INVALID; + } + } + } + } + +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (value); +#endif /* JERRY_BUILTIN_CONTAINER */ + return JERRY_CONTAINER_TYPE_INVALID; +} /* jerry_container_type */ + +/** + * Return a new array containing elements from a Container or a Container Iterator. + * Sets the boolean input value to `true` if the container object has key/value pairs. + * + * Note: + * the returned value must be freed with a jerry_value_free call + * + * @return an array of items for maps/sets or their iterators, error otherwise + */ +jerry_value_t +jerry_container_to_array (const jerry_value_t value, /**< the container or iterator object */ + bool *is_key_value_p) /**< [out] is key-value structure */ +{ +#if JERRY_BUILTIN_CONTAINER + if (!ecma_is_value_object (value)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NEEDED)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_CLASS) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NEEDED)); + } + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + uint32_t entry_count; + uint8_t entry_size; + + uint32_t index = 0; + uint8_t iterator_kind = ECMA_ITERATOR__COUNT; + ecma_value_t *start_p; + + *is_key_value_p = false; + + if (ext_obj_p->u.cls.type == ECMA_OBJECT_CLASS_MAP_ITERATOR + || ext_obj_p->u.cls.type == ECMA_OBJECT_CLASS_SET_ITERATOR) + { + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + if (ecma_is_value_empty (iterated_value)) + { + return ecma_op_new_array_object_from_collection (ecma_new_collection (), false); + } + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) (ecma_get_object_from_value (iterated_value)); + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + index = ext_obj_p->u.cls.u2.iterator_index; + + entry_size = ecma_op_container_entry_size ((lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); + start_p = ECMA_CONTAINER_START (container_p); + + iterator_kind = ext_obj_p->u.cls.u1.iterator_kind; + } + else if (jerry_container_type (value) != JERRY_CONTAINER_TYPE_INVALID) + { + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, ext_obj_p->u.cls.u3.value); + entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + entry_size = ecma_op_container_entry_size ((lit_magic_string_id_t) ext_obj_p->u.cls.u2.container_id); + + index = 0; + iterator_kind = ECMA_ITERATOR_KEYS; + start_p = ECMA_CONTAINER_START (container_p); + + if (ext_obj_p->u.cls.u2.container_id == LIT_MAGIC_STRING_MAP_UL + || ext_obj_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL) + { + iterator_kind = ECMA_ITERATOR_ENTRIES; + } + } + else + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NEEDED)); + } + + *is_key_value_p = (iterator_kind == ECMA_ITERATOR_ENTRIES); + ecma_collection_t *collection_buffer = ecma_new_collection (); + + for (uint32_t i = index; i < entry_count; i += entry_size) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + if (iterator_kind != ECMA_ITERATOR_VALUES) + { + ecma_collection_push_back (collection_buffer, ecma_copy_value_if_not_object (entry_p[0])); + } + + if (iterator_kind != ECMA_ITERATOR_KEYS) + { + ecma_collection_push_back (collection_buffer, ecma_copy_value_if_not_object (entry_p[1])); + } + } + return ecma_op_new_array_object_from_collection (collection_buffer, false); +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (value); + JERRY_UNUSED (is_key_value_p); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_CONTAINER */ +} /* jerry_container_to_array */ + +/** + * Perform container operation on the given operands (add, get, set, has, delete, size, clear). + * + * @return error - if argument is invalid or operation is unsuccessful or unsupported + * result of the container operation - otherwise. + */ +jerry_value_t +jerry_container_op (jerry_container_op_t operation, /**< container operation */ + jerry_value_t container, /**< container */ + const jerry_value_t *arguments, /**< list of arguments */ + uint32_t arguments_number) /**< number of arguments */ +{ +#if JERRY_BUILTIN_CONTAINER + if (!ecma_is_value_object (container)) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_IS_NOT_AN_OBJECT)); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (container); + + if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_CLASS) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_IS_NOT_A_CONTAINER_OBJECT)); + } + uint16_t type = ((ecma_extended_object_t *) obj_p)->u.cls.u2.container_id; + ecma_extended_object_t *container_object_p = ecma_op_container_get_object (container, (lit_magic_string_id_t) type); + + if (container_object_p == NULL) + { + return ecma_create_exception_from_context (); + } + + switch (operation) + { + case JERRY_CONTAINER_OP_ADD: + case JERRY_CONTAINER_OP_DELETE: + case JERRY_CONTAINER_OP_GET: + case JERRY_CONTAINER_OP_HAS: + { + if (arguments_number != 1 || ecma_is_value_exception (arguments[0])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + break; + } + case JERRY_CONTAINER_OP_SET: + { + if (arguments_number != 2 || ecma_is_value_exception (arguments[0]) || ecma_is_value_exception (arguments[1])) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + break; + } + case JERRY_CONTAINER_OP_CLEAR: + case JERRY_CONTAINER_OP_SIZE: + { + if (arguments_number != 0) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + break; + } + default: + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); + } + } + + jerry_value_t result; + + switch (operation) + { + case JERRY_CONTAINER_OP_ADD: + { + if (type == LIT_MAGIC_STRING_MAP_UL || type == LIT_MAGIC_STRING_WEAKMAP_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_set (container_object_p, arguments[0], arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_GET: + { + if (type == LIT_MAGIC_STRING_SET_UL || type == LIT_MAGIC_STRING_WEAKSET_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_get (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_SET: + { + if (type == LIT_MAGIC_STRING_SET_UL || type == LIT_MAGIC_STRING_WEAKSET_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_set (container_object_p, arguments[0], arguments[1], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_HAS: + { + result = ecma_op_container_has (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_DELETE: + { + if (type == LIT_MAGIC_STRING_WEAKMAP_UL || type == LIT_MAGIC_STRING_WEAKSET_UL) + { + result = ecma_op_container_delete_weak (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + result = ecma_op_container_delete (container_object_p, arguments[0], (lit_magic_string_id_t) type); + break; + } + case JERRY_CONTAINER_OP_SIZE: + { + result = ecma_op_container_size (container_object_p); + break; + } + case JERRY_CONTAINER_OP_CLEAR: + { + if (type == LIT_MAGIC_STRING_WEAKSET_UL || type == LIT_MAGIC_STRING_WEAKMAP_UL) + { + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_INCORRECT_TYPE_CALL)); + } + result = ecma_op_container_clear (container_object_p); + break; + } + default: + { + result = jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_UNSUPPORTED_CONTAINER_OPERATION)); + break; + } + } + return jerry_return (result); +#else /* !JERRY_BUILTIN_CONTAINER */ + JERRY_UNUSED (operation); + JERRY_UNUSED (container); + JERRY_UNUSED (arguments); + JERRY_UNUSED (arguments_number); + return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_CONTAINER_NOT_SUPPORTED)); +#endif /* JERRY_BUILTIN_CONTAINER */ +} /* jerry_container_op */ + +/** + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/api/meson.build b/src/loaders/lottie/jerryscript/jerry-core/api/meson.build new file mode 100644 index 00000000..b20f50cd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/api/meson.build @@ -0,0 +1,8 @@ +source_file = [ + 'jerryscript.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.cpp new file mode 100644 index 00000000..0a39565b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.cpp @@ -0,0 +1,232 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" + +#include "ecma-gc.h" +#include "ecma-globals.h" + +#include "jmem.h" +#include "jrt.h" + +JERRY_STATIC_ASSERT ((sizeof (ecma_property_value_t) == sizeof (ecma_value_t)), + size_of_ecma_property_value_t_must_be_equal_to_size_of_ecma_value_t); +JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_property_value_t)) == 0, + size_of_ecma_property_value_t_must_be_power_of_2); + +JERRY_STATIC_ASSERT ((sizeof (ecma_extended_object_t) - sizeof (ecma_object_t) <= sizeof (uint64_t)), + size_of_ecma_extended_object_part_must_be_less_than_or_equal_to_8_bytes); + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types + * @{ + */ + +/** + * Implementation of routines for allocation/freeing memory for ECMA data types. + * + * All allocation routines from this module have the same structure: + * 1. Try to allocate memory. + * 2. If allocation was successful, return pointer to the allocated block. + * 3. Run garbage collection. + * 4. Try to allocate memory. + * 5. If allocation was successful, return pointer to the allocated block; + * else - shutdown engine. + */ + +/** + * Allocate memory for ecma-number + * + * @return pointer to allocated memory + */ +ecma_number_t * +ecma_alloc_number (void) +{ + return (ecma_number_t *) jmem_pools_alloc (sizeof (ecma_number_t)); +} /* ecma_alloc_number */ + +/** + * Dealloc memory from an ecma-number + * + * @return void + */ +void +ecma_dealloc_number (ecma_number_t *number_p) /**< number to be freed */ +{ + jmem_pools_free ((uint8_t *) number_p, sizeof (ecma_number_t)); +} /* ecma_dealloc_number */ + +/** + * Allocate memory for ecma-object + * + * @return pointer to allocated memory + */ +ecma_object_t * +ecma_alloc_object (void) +{ + return (ecma_object_t *) jmem_pools_alloc (sizeof (ecma_object_t)); +} /* ecma_alloc_object */ + +/** + * Dealloc memory from an ecma-object + * + * @return void + */ +void +ecma_dealloc_object (ecma_object_t *object_p) /**< object to be freed */ +{ + jmem_pools_free (object_p, sizeof (ecma_object_t)); +} /* ecma_dealloc_object */ + +/** + * Allocate memory for extended object + * + * @return pointer to allocated memory + */ +ecma_extended_object_t * +ecma_alloc_extended_object (size_t size) /**< size of object */ +{ + return (ecma_extended_object_t *) jmem_heap_alloc_block (size); +} /* ecma_alloc_extended_object */ + +/** + * Dealloc memory of an extended object + * + * @return void + */ +void +ecma_dealloc_extended_object (ecma_object_t *object_p, /**< extended object */ + size_t size) /**< size of object */ +{ + jmem_heap_free_block (object_p, size); +} /* ecma_dealloc_extended_object */ + +/** + * Allocate memory for ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_string_t * +ecma_alloc_string (void) +{ + return (ecma_string_t *) jmem_pools_alloc (sizeof (ecma_string_t)); +} /* ecma_alloc_string */ + +/** + * Dealloc memory from ecma-string descriptor + * + * @return void + */ +void +ecma_dealloc_string (ecma_string_t *string_p) /**< string to be freed */ +{ + jmem_pools_free (string_p, sizeof (ecma_string_t)); +} /* ecma_dealloc_string */ + +/** + * Allocate memory for extended ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_extended_string_t * +ecma_alloc_extended_string (void) +{ + return (ecma_extended_string_t *) jmem_heap_alloc_block (sizeof (ecma_extended_string_t)); +} /* ecma_alloc_extended_string */ + +/** + * Dealloc memory from extended ecma-string descriptor + * + * @return void + */ +void +ecma_dealloc_extended_string (ecma_extended_string_t *ext_string_p) /**< extended string to be freed */ +{ + jmem_heap_free_block (ext_string_p, sizeof (ecma_extended_string_t)); +} /* ecma_dealloc_extended_string */ + +/** + * Allocate memory for external ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_external_string_t * +ecma_alloc_external_string (void) +{ + return (ecma_external_string_t *) jmem_heap_alloc_block (sizeof (ecma_external_string_t)); +} /* ecma_alloc_external_string */ + +/** + * Dealloc memory from external ecma-string descriptor + * + * @return void + */ +void +ecma_dealloc_external_string (ecma_external_string_t *ext_string_p) /**< external string to be freed */ +{ + jmem_heap_free_block (ext_string_p, sizeof (ecma_external_string_t)); +} /* ecma_dealloc_external_string */ + +/** + * Allocate memory for an string with character data + * + * @return pointer to allocated memory + */ +ecma_string_t * +ecma_alloc_string_buffer (size_t size) /**< size of string */ +{ + return (ecma_string_t *) jmem_heap_alloc_block (size); +} /* ecma_alloc_string_buffer */ + +/** + * Dealloc memory of a string with character data + * + * @return void + */ +void +ecma_dealloc_string_buffer (ecma_string_t *string_p, /**< string with data */ + size_t size) /**< size of string */ +{ + jmem_heap_free_block (string_p, size); +} /* ecma_dealloc_string_buffer */ + +/** + * Allocate memory for ecma-property pair + * + * @return pointer to allocated memory + */ +ecma_property_pair_t * +ecma_alloc_property_pair (void) +{ + return (ecma_property_pair_t *) jmem_heap_alloc_block (sizeof (ecma_property_pair_t)); +} /* ecma_alloc_property_pair */ + +/** + * Dealloc memory of an ecma-property + * + * @return void + */ +void +ecma_dealloc_property_pair (ecma_property_pair_t *property_pair_p) /**< property pair to be freed */ +{ + jmem_heap_free_block (property_pair_p, sizeof (ecma_property_pair_t)); +} /* ecma_dealloc_property_pair */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.h new file mode 100644 index 00000000..a5af9d1a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-alloc.h @@ -0,0 +1,129 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ALLOC_H +#define ECMA_ALLOC_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types + * @{ + */ + +/** + * Allocate memory for ecma-object + * + * @return pointer to allocated memory + */ +ecma_object_t *ecma_alloc_object (void); + +/** + * Dealloc memory from an ecma-object + */ +void ecma_dealloc_object (ecma_object_t *object_p); + +/** + * Allocate memory for extended object + * + * @return pointer to allocated memory + */ +ecma_extended_object_t *ecma_alloc_extended_object (size_t size); + +/** + * Dealloc memory of an extended object + */ +void ecma_dealloc_extended_object (ecma_object_t *object_p, size_t size); + +/** + * Allocate memory for ecma-number + * + * @return pointer to allocated memory + */ +ecma_number_t *ecma_alloc_number (void); + +/** + * Dealloc memory from an ecma-number + */ +void ecma_dealloc_number (ecma_number_t *number_p); + +/** + * Allocate memory for ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_string_t *ecma_alloc_string (void); + +/** + * Dealloc memory from ecma-string descriptor + */ +void ecma_dealloc_string (ecma_string_t *string_p); + +/** + * Allocate memory for extended ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_extended_string_t *ecma_alloc_extended_string (void); + +/** + * Dealloc memory from extended ecma-string descriptor + */ +void ecma_dealloc_extended_string (ecma_extended_string_t *string_p); + +/** + * Allocate memory for external ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_external_string_t *ecma_alloc_external_string (void); + +/** + * Dealloc memory from external ecma-string descriptor + */ +void ecma_dealloc_external_string (ecma_external_string_t *string_p); + +/** + * Allocate memory for string with character data + * + * @return pointer to allocated memory + */ +ecma_string_t *ecma_alloc_string_buffer (size_t size); + +/** + * Dealloc memory of a string with character data + */ +void ecma_dealloc_string_buffer (ecma_string_t *string_p, size_t size); + +/** + * Allocate memory for ecma-property pair + * + * @return pointer to allocated memory + */ +ecma_property_pair_t *ecma_alloc_property_pair (void); + +/** + * Dealloc memory from an ecma-property pair + */ +void ecma_dealloc_property_pair (ecma_property_pair_t *property_pair_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ALLOC_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.inc.h new file mode 100644 index 00000000..ff4d936e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.inc.h @@ -0,0 +1,743 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-strings.py script + * from ecma-error-messages.ini. Do not edit! */ + +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_GROUP, "Invalid group") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ESCAPE, "Invalid escape") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_LENGTH, "Invalid length") +#endif /* JERRY_BUILTIN_ATOMICS \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_OFFSET, "Invalid offset") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_EXPECTED, "Object expected") +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARGUMENT, "Invalid argument") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ENCODING, "Invalid encoding") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_NOTHING_TO_REPEAT, "Nothing to repeat") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_AN_OBJECT, "Expected an object") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CAPABILITY, "Invalid capability") +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CODE_POINT, "Invalid code point") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_QUANTIFIER, "Invalid quantifier") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_NO_SOURCE_ARGUMENT, "No source argument") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNTERMINATED_GROUP, "Unterminated group") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_FUNCTION, "Expected a function") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UTF8_STRING, "Invalid UTF8 string") +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_COUNT_VALUE, "Invalid count value") +#endif /* JERRY_BUILTIN_STRING */ +#if !(JERRY_BUILTIN_REALMS) +ECMA_ERROR_DEF (ECMA_ERR_REALMS_ARE_DISABLED, "Realms are disabled") +#endif /* !(JERRY_BUILTIN_REALMS) */ +ECMA_ERROR_DEF (ECMA_ERR_UNDEFINED_REFERENCE, "Undefined reference") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARRAY_LENGTH, "Invalid Array length") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_REGEXP_FLAGS, "Invalid RegExp flags") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_STACK_LIMIT_EXCEEDED, "Stack limit exceeded") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_TARGET_IS_NOT_OBJECT, "Target is not Object") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_VALUE_EXCPECTED, "BigInt value expected") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_BINDING_CANNOT_SET, "Binding cannot be set") +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_STRING_, "Invalid string length") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_KEY_MUST_BE_AN_OBJECT, "Key must be an object") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_MISSING_ARRAY_ELEMENT, "Missing Array element") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_TARGET_IS_NOT_WEAKREF, "Target is not weakRef") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TARGET_NOT_EXTENSIBLE, "Target not extensible") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_ANNEXB +ECMA_ERROR_DEF (ECMA_ERR_GETTER_IS_NOT_CALLABLE, "Getter is not callable") +#endif /* JERRY_BUILTIN_ANNEXB */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_HANDLER_CANNOT_BE_NULL, "Handler cannot be null") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UTF8_CHARACTER, "Invalid UTF8 character") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UTF8_CODEPOINT, "Invalid UTF8 codepoint") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CONTAINER_TYPE, "Invalid container type") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_RANGE_OF_INDEX, "Invalid range of index") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if !(JERRY_BUILTIN_PROXY) +ECMA_ERROR_DEF (ECMA_ERR_PROXY_IS_NOT_SUPPORTED, "Proxy is not supported") +#endif /* !(JERRY_BUILTIN_PROXY) */ +#if !(JERRY_BUILTIN_REALMS) +ECMA_ERROR_DEF (ECMA_ERR_REALM_IS_NOT_AVAILABLE, "Realm is not available") +#endif /* !(JERRY_BUILTIN_REALMS) */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_ZERO_DIVISION, "BigInt division by zero") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_AN_ARRAYBUFFER, "Expected an ArrayBuffer") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CHARACTER_CLASS, "Invalid character class") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ESCAPE_SEQUENCE, "Invalid escape sequence") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SNAPSHOT_FORMAT, "Invalid snapshot format") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_LONE_QUANTIFIER_BRACKET, "Lone quantifier bracket") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_CANNOT_BE_FROZEN, "Object cannot be frozen") +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_CANNOT_BE_SEALED, "Object cannot be sealed") +#endif /* JERRY_BUILTIN_PROXY */ +#if !(JERRY_BUILTIN_REGEXP) +ECMA_ERROR_DEF (ECMA_ERR_REGEXP_IS_NOT_SUPPORTED, "RegExp is not supported") +#endif /* !(JERRY_BUILTIN_REGEXP) */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNMATCHED_CLOSE_BRACKET, "Unmatched close bracket") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_NOT_MODULE, "Argument is not a module") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_SET_PROTOTYPE, "Cannot set [[Prototype]]") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_NEW_ARRAY_LENGTH, "Invalid new Array length") +#endif /* JERRY_BUILTIN_ARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_IS_NOT_CALLABLE, "Iterator is not callable") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_IS_IN_ERROR_STATE, "Module is in error state") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_REJECT_MUST_BE_UNDEFINED, "Reject must be undefined") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_REQUEST_IS_NOT_AVAILABLE, "Request is not available") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT, "Argument is not an object") +#if JERRY_BUILTIN_ATOMICS +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_SUPPORTED, "Argument is not supported") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CODE_POINT_ERROR, "Error: Invalid code point") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_TYPEDARRAY_LENGTH, "Invalid TypedArray length") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_HEXADECIMAL_VALUE, "Invalid hexadecimal value") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_IS_NOT_AN_OBJECT, "Iterator is not an object") +ECMA_ERROR_DEF (ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED, "Resolve must be undefined") +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_BUFFER_SMALL, "Snapshot buffer too small") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNEXPECTED_END_OF_PATTERN, "Unexpected end of pattern") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_UNSUPPORTED_COMPILED_CODE, "Unsupported compiled code") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if !(JERRY_BUILTIN_BIGINT) +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_NOT_SUPPORTED, "BigInt support is disabled") +#endif /* !(JERRY_BUILTIN_BIGINT) */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_DATAVIEW_OBJECT, "Expected a DataView object") +#endif /* JERRY_BUILTIN_DATAVIEW */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT, "Expected a function object") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARRAYBUFFER_LENGTH, "Invalid ArrayBuffer length") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if !(JERRY_MODULE_SYSTEM) +ECMA_ERROR_DEF (ECMA_ERR_MODULE_NOT_SUPPORTED, "Module support is disabled") +#endif /* !(JERRY_MODULE_SYSTEM) */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_OBJECT_IS_NOT_A_TYPEDARRAY, "Object is not a TypedArray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT, "Receiver must be an object") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_SERIALIZED, "BigInt cannot be serialized") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_IS_NOT_AN_OBJECT, "Container is not an object.") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_HEX_ESCAPE_SEQUENCE, "Invalid hex escape sequence") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SPECIES_CONSTRUCTOR, "Invalid species constructor") +ECMA_ERROR_DEF (ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH, "Proxy trap returned falsish") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_MIN_GREATER_THAN_MAX, "Quantifier error: min > max") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_SYMBOL_IS_NOT_A_CONSTRUCTOR, "Symbol is not a constructor") +#if JERRY_BUILTIN_REFLECT +ECMA_ERROR_DEF (ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR, "Target is not a constructor") +#endif /* JERRY_BUILTIN_REFLECT */ +ECMA_ERROR_DEF (ECMA_ERR_ACCESSOR_WRITABLE, "Accessors cannot be writable") +#if !(JERRY_BUILTIN_DATAVIEW) +ECMA_ERROR_DEF (ECMA_ERR_DATA_VIEW_NOT_SUPPORTED, "DataView support is disabled") +#endif /* !(JERRY_BUILTIN_DATAVIEW) */ +#if JERRY_BUILTIN_DATE +ECMA_ERROR_DEF (ECMA_ERR_DATE_MUST_BE_A_FINITE_NUMBER, "Date must be a finite number") +#endif /* JERRY_BUILTIN_DATE */ +ECMA_ERROR_DEF (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED, "Local variable is redeclared") +ECMA_ERROR_DEF (ECMA_ERR_UNSUPPORTED_BINARY_OPERATION, "Unsupported binary operation") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_UNTERMINATED_CHARACTER_CLASS, "Unterminated character class") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_ARRAYBUFFER_IS_DETACHED, "ArrayBuffer has been detached") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_NOT_AN_OBJECT, "Constructor must be an object") +#if !(JERRY_BUILTIN_CONTAINER) +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_NOT_SUPPORTED, "Container support is disabled") +#endif /* !(JERRY_BUILTIN_CONTAINER) */ +#if JERRY_BUILTIN_REALMS +ECMA_ERROR_DEF (ECMA_ERR_FIRST_ARGUMENT_IS_NOT_A_REALM, "First argument is not a realm") +#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INCOMPATIBLE_TYPEDARRAY_TYPES, "Incompatible TypedArray types") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY, "Incorrect type for TypedArray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_OR_OUT_OF_RANGE_INDEX, "Invalid or out-of-range index") +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_SNAPSHOT_SIZE, "Maximum snapshot size reached") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_CANNOT_BE_INSTANTIATED, "Module cannot be instantiated") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_SPECIES_MUST_BE_A_CONSTRUCTOR, "Species must be a constructor") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY, "Argument is not a Proxy object") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER, "Argument is not an ArrayBuffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_MAP_REQUIRES_NEW, "Constructor Map requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_SET_REQUIRES_NEW, "Constructor Set requires 'new'") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_MUST_BE_IN_LINKED_STATE, "Module must be in linked state") +ECMA_ERROR_DEF (ECMA_ERR_UNKNOWN_EXPORT, "Native module export not found") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM, "Passed argument is not a realm") +ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE, "Private method is not writable") +#if JERRY_BUILTIN_BIGINT || JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_RADIX_IS_OUT_OF_RANGE, "Radix must be between 2 and 36") +#endif /* JERRY_BUILTIN_BIGINT \ +|| JERRY_BUILTIN_NUMBER */ +#if !(JERRY_SNAPSHOT_EXEC) +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_EXEC_DISABLED, "Snapshot execution is disabled") +#endif /* !(JERRY_SNAPSHOT_EXEC) */ +#if !(JERRY_BUILTIN_TYPEDARRAY) +ECMA_ERROR_DEF (ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED, "TypedArray support is disabled") +#endif /* !(JERRY_BUILTIN_TYPEDARRAY) */ +ECMA_ERROR_DEF (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING, "Unicode surrogate pair missing") +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_INVALID_CONTROL_ESCAPE_SEQUENCE, "Invalid control escape sequence") +ECMA_ERROR_DEF (ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE, "Invalid unicode escape sequence") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_NEXT_IS_NOT_CALLABLE, "Iterator 'next' is not callable") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT, "Iterator value is not an object") +ECMA_ERROR_DEF (ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE, "Resolve method must be callable") +#if !(JERRY_SNAPSHOT_SAVE) +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_SAVE_DISABLED, "Snapshot generation is disabled") +#endif /* !(JERRY_SNAPSHOT_SAVE) */ +#if !(JERRY_PARSER) +ECMA_ERROR_DEF (ECMA_ERR_PARSER_NOT_SUPPORTED, "Source code parsing is disabled") +#endif /* !(JERRY_PARSER) */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_MUST_RETURN_WITH_AN_OBJECT, "Trap must return with an object") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_UNSUPPORTED_CONTAINER_OPERATION, "Unsupported container operation") +#endif /* JERRY_BUILTIN_CONTAINER */ +ECMA_ERROR_DEF (ECMA_ERR_METHOD_RETURN_IS_NOT_CALLABLE, "method 'return' is not callable") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_PROMISE, "Argument 'this' is not a Promise") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT, "Argument 'this' is not an object") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_SYMBOL, "Argument 'this' must be a Symbol") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_CALLBACK_RESULT_NOT_MODULE, "Callback result must be a module") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW, "Class constructor requires 'new'") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_COMPARE_FUNC_NOT_CALLABLE, "Compare function is not callable") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_PROXY_REQUIRES_NEW, "Constructor Proxy requires 'new'") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY, "Expected a configurable property") +ECMA_ERROR_DEF (ECMA_ERR_FIRST_PARAMETER_MUST_BE_CALLABLE, "First parameter must be callable") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_FUNCTION_ADD_ORSET_IS_NOT_CALLABLE, "Function add/set is not callable") +#endif /* JERRY_BUILTIN_CONTAINER */ +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT, "Iterator result is not an object") +#if (JERRY_STACK_LIMIT != 0) +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED, "Maximum call stack size exceeded") +#endif /* (JERRY_STACK_LIMIT != 0) */ +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_STRING_LENGTH_IS_REACHED, "Maximum string length is reached") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_MUST_BE_IN_UNLINKED_STATE, "Module must be in unlinked state") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_STATIC_SNAPSHOTS_ARE_NOT_ENABLED, "Static snapshots are not enabled") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_WEAKREF_TARGET_MUST_BE_AN_OBJECT, "WeakRef target must be an object") +#endif /* JERRY_BUILTIN_WEAKREF */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION, "Argument 'this' is not a function") +#if JERRY_BUILTIN_ATOMICS +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER, "Argument is not SharedArrayBuffer") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_CONTAINER || JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE, "Callback function is not callable") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_CONTAINER \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_INITIAL_VALUE_CANNOT_BE_UNDEFINED, "Initial value cannot be undefined") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SHARED_ARRAYBUFFER_LENGTH, "Invalid Shared ArrayBuffer length") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +ECMA_ERROR_DEF (ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL, "Invalid type for constructor call") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE, "Iterator 'throw' is not available") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_NAMESPACE_OBJECT_IS_NOT_AVAILABLE, "Namespace object is not available") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR, "Proxy target is not a constructor") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_REALMS +ECMA_ERROR_DEF (ECMA_ERR_SECOND_ARGUMENT_MUST_BE_AN_OBJECT, "Second argument must be an object") +#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_BUFFER_NOT_OBJECT, "Argument 'buffer' is not an object") +#endif /* JERRY_BUILTIN_DATAVIEW */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR, "Argument 'this' is not an iterator") +ECMA_ERROR_DEF (ECMA_ERR_VALUE_MSG, "Argument cannot be marked as error") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_PROMISE_REQUIRES_NEW, "Constructor Promise requires 'new'") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_WEAKMAP_REQUIRES_NEW, "Constructor WeakMap requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_WEAKSET_REQUIRES_NEW, "Constructor WeakSet requires 'new'") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED, "Maximum TypedArray size is reached") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL, "The given argument is not a Symbol") +ECMA_ERROR_DEF (ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE, "'reject' parameter must be callable") +#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY, "Argument 'this' is not a TypedArray") +#endif /* JERRY_BUILTIN_ATOMICS \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_ALLOCATE_MEMORY_LITERALS, "Cannot allocate memory for literals") +#endif /* JERRY_SNAPSHOT_SAVE */ +ECMA_ERROR_DEF (ECMA_ERR_INVOKE_NULLABLE_SUPER_METHOD, "Cannot invoke nullable super method") +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_DATAVIEW_REQUIRES_NEW, "Constructor DataView requires 'new'") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_WEAKREF +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_WEAKREF_REQUIRES_NEW, "Constructor WeakRef requires 'new'.") +#endif /* JERRY_BUILTIN_WEAKREF */ +ECMA_ERROR_DEF (ECMA_ERR_SUPER_BINDING_MUST_BE_A_CONSTRUCTOR, "Super binding must be a constructor") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_VALUE_CANNOT_BE_CONVERTED_TO_BIGINT, "Value cannot be converted to BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_PARAMETER_RESOLVE_MUST_BE_CALLABLE, "'resolve' parameter must be callable") +#if JERRY_BUILTIN_DATE +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT, "Argument 'this' is not a Date object") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR, "Argument 'this' is not a constructor") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_BIGINT_FUNCTION_NOT_CONSTRUCTOR, "BigInt function is not a constructor") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTED_OBJECT_IS_NOT_TYPEDARRAY, "Constructed object is not TypedArray") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_INT8_ARRAY_REQUIRES_NEW, "Constructor Int8Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_IS_NOT_A_CONTAINER_OBJECT, "Container is not a container object.") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_DATE +ECMA_ERROR_DEF (ECMA_ERR_INVALID_ARGUMENT_TYPE_IN_TOPRIMITIVE, "Invalid argument type in toPrimitive") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_METHODS_INVOKE_WITH_NEW, "Methods cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_EXPORTS_MUST_BE_STRING_VALUES, "Module exports must be string values") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL, "Prototype is neither object nor null") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_THE_MAPFN_ARGUMENT_IS_NOT_CALLABLE, "The 'mapfn' argument is not callable") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE, "The two descriptors are incompatible") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_WRONG_ARGS_MSG, "This type of argument is not allowed") +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_CONTAINER_NEEDED, "Value is not a Container or Iterator") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP, "Argument 'this' is not a valid RegExp") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARRAY_BUFFER_DETACHED, "ArrayBuffer has already been detached") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR, "Built-in routines have no constructor") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_INT16_ARRAY_REQUIRES_NEW, "Constructor Int16Array requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_INT32_ARRAY_REQUIRES_NEW, "Constructor Int32Array requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT8_ARRAY_REQUIRES_NEW, "Constructor Uint8Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_FUNCTION_INDEX_IS_HIGHER_THAN_MAXIMUM, "Function index is higher than maximum") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_RANGE_OUT_OF_ORDER_IN_CHARACTER_CLASS, "Range out of order in character class") +#endif /* JERRY_BUILTIN_REGEXP */ +ECMA_ERROR_DEF (ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID, "Result of [[DefaultValue]] is invalid") +ECMA_ERROR_DEF (ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT, "Right value of 'in' must be an object") +#if !(JERRY_BUILTIN_SHAREDARRAYBUFFER) +ECMA_ERROR_DEF (ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED, "SharedArrayBuffer support is disabled") +#endif /* !(JERRY_BUILTIN_SHAREDARRAYBUFFER) */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL, "Trap returned neither object nor null") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_WITH_DUPLICATED_ENTRIES, "Trap returned with duplicated entries") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_UNARY_PLUS_IS_NOT_ALLOWED_FOR_BIGINTS, "Unary plus is not allowed for BigInts") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP, "Argument 'this' is not a RegExp object") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ALLOCATE_ARRAY_BUFFER, "Cannot allocate memory for ArrayBuffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED, "Constant bindings cannot be reassigned") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_ARRAYBUFFER_REQUIRES_NEW, "Constructor ArrayBuffer requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT16_ARRAY_REQUIRES_NEW, "Constructor Uint16Array requires 'new'") +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW, "Constructor Uint32Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION, "Generator is currently under execution") +ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT, "Iterator 'return' result is not object") +ECMA_ERROR_DEF (ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP, "Search string can't be of type: RegExp") +ECMA_ERROR_DEF (ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT, "Value received by yield* is not object") +#if JERRY_BUILTIN_BOOLEAN +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_BOOLEAN_OBJECT, "Argument 'this' is not a Boolean object") +#endif /* JERRY_BUILTIN_BOOLEAN */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE, "Cannot declare same private field twice") +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_FLOAT32_ARRAY_REQUIRES_NEW, "Constructor Float32Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_FLOAT64_ARRAY_REQUIRES_NEW, "Constructor Float64Array requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 */ +ECMA_ERROR_DEF (ECMA_ERR_FUNCTION_PROTOTYPE_NOT_A_CONSTRUCTOR, "Function.prototype is not a constructor") +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_IMPORTED_BINDING_SHADOWS_LOCAL_VARIABLE, "Imported binding shadows local variable") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID, "Prototype from revoked Proxy is invalid") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG, "RegExp argument should have global flag") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED, "Trap is neither an object nor undefined") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_PROMISE_RESOLVE_ITSELF, "A promise cannot be resolved with itself") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_BIGINT64_ARRAY_REQUIRES_NEW, "Constructor BigInt64Array requires 'new'") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_MODULE_EXPORTS_MUST_BE_VALID_IDENTIFIERS, "Module exports must be valid identifiers") +#endif /* JERRY_MODULE_SYSTEM */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_GENERATOR_OBJECT, "Argument 'this' is not a generator object") +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT, "Argument cannot be converted to an object") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_ALLOCATE_BIGINT_VALUE, "Cannot allocate memory for a BigInt value") +ECMA_ERROR_DEF (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER, "Cannot convert a BigInt value to a number") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_CONVERT_SYMBOL_TO_NUMBER, "Cannot convert a Symbol value to a number") +ECMA_ERROR_DEF (ECMA_ERR_CONVERT_SYMBOL_TO_STRING, "Cannot convert a Symbol value to a string") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_BIG_UINT64_ARRAY_REQUIRES_NEW, "Constructor BigUInt64Array requires 'new'") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE, "Fraction digits must be between 0 and 100") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT, "Return value is not an ArrayBuffer object") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_SUPER_CONSTRUCTOR_MAY_ONLY_BE_CALLED_ONCE, "Super constructor may only be called once") +ECMA_ERROR_DEF (ECMA_ERR_BINDING_NOT_EXIST_OR_UNINITIALIZED, "Binding does not exist or is uninitialised") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_CONVERT_TO_OBJECT, "Cannot convert undefined or null to object") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_PRECISION_DIGITS_MUST_BE_BETWEEN_IN_RANGE, "Precision digits must be between 1 and 100") +#endif /* JERRY_BUILTIN_NUMBER */ +ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER, "Private field was defined without a getter") +ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER, "Private field was defined without a setter") +ECMA_ERROR_DEF (ECMA_ERR_PROPERTY_NAME_IS_NEITHER_SYMBOL_NOR_STRING, "Property name is neither Symbol nor string") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_STRING_CANNOT_BE_CONVERTED_TO_BIGINT_VALUE, "String cannot be converted to BigInt value") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_CONTAINER +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_TYPE_CALL, "Operator called on incorrect container type") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE, "Reduce of empty Array with no initial value") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP_OBJECT, "Argument 'this' is not a valid RegExp object") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT, "Argument 'this' is not an ArrayBuffer object") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ARROW_FUNCTIONS_INVOKE_WITH_NEW, "Arrow functions cannot be invoked with 'new'") +ECMA_ERROR_DEF (ECMA_ERR_ASYNC_FUNCTIONS_INVOKE_WITH_NEW, "Async functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_SET_EXTENSIBLE_PROPERTY, "Cannot set [[Extensible]] property of object") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_SHAREDARRAYBUFFER_REQUIRES_NEW, "Constructor SharedArrayBuffer requires 'new'") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT8_CLAMPED_ARRAY_REQUIRES_NEW, "Constructor Uint8ClampedArray requires 'new'") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_NEGATIVE_EXPONENT_IS_NOT_ALLOWED_FOR_BIGINTS, "Negative exponent is not allowed for BigInts") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_PROMISE_ALL_REMAINING_ELEMENTS_LIMIT_REACHED, "Promise.all remaining elements limit reached") +ECMA_ERROR_DEF (ECMA_ERR_VALUE_RECEIVED_BY_FOR_ASYNC_OF_IS_NOT_OBJECT, "Value received by for-async-of is not object") +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_INFINITY_OR_NAN_CANNOT_BE_CONVERTED_TO_BIGINT, "Infinity or NaN cannot be converted to BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_OPERATOR_DELETE_RETURNED_FALSE_IN_STRICT_MODE, "Operator delete returned false in strict mode") +ECMA_ERROR_DEF (ECMA_ERR_PROPERTY_PROTOTYPE_IS_NOT_AN_OBJECT, "Property 'prototype' is not an object or null") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_PROXY_HANDLER_IS_NULL_FOR_ISARRAY_OPERATION, "Proxy handler is null for 'isArray' operation") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_REGULAR_EXPRESSION_NOT_SUPPORTED, "Regular expression literals are not supported") +#endif /* JERRY_SNAPSHOT_SAVE */ +ECMA_ERROR_DEF (ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT, "Right value of 'instanceof' must be an object") +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_STATIC_SNAPSHOTS_CANNOT_BE_COPIED_INTO_MEMORY, "Static snapshots cannot be copied into memory") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_SNAPSHOT_SAVE +ECMA_ERROR_DEF (ECMA_ERR_TAGGED_TEMPLATE_LITERALS, "Unsupported feature: tagged template literals") +ECMA_ERROR_DEF (ECMA_ERR_SNAPSHOT_FLAG_NOT_SUPPORTED, "Unsupported generate snapshot flags specified") +#endif /* JERRY_SNAPSHOT_SAVE */ +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_UNSUPPORTED_SNAPSHOT_EXEC_FLAGS_ARE_SPECIFIED, "Unsupported snapshot exec flags are specified") +#endif /* JERRY_SNAPSHOT_EXEC */ +ECMA_ERROR_DEF (ECMA_ERR_VALUE_FOR_CLASS_HERITAGE_IS_NOT_A_CONSTRUCTOR, "Value for class heritage is not a constructor") +ECMA_ERROR_DEF (ECMA_ERR_TOO_MANY_ARGUMENTS_DECLARED_FOR_FUNCTION_APPLY, + "Too many arguments declared for Function.apply") +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ACCESSOR_FUNCTIONS_INVOKE_WITH_NEW, "Accessor functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_MODULE_SYSTEM +ECMA_ERROR_DEF (ECMA_ERR_LINK_TO_MODULE_IN_ERROR_STATE, "Cannot link to a module which is in error state") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_ONLY_INTEGER_NUMBERS_CAN_BE_CONVERTED_TO_BIGINT, + "Only integer numbers can be converted to BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_TYPEDARRAY_INTRINSTIC_DIRECTLY_CALLED, "TypedArray intrinstic cannot be directly called") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_UNSIGNED_RIGHT_SHIFT_IS_NOT_ALLOWED_FOR_BIGINTS, + "Unsigned right shift is not allowed for BigInts") +#endif /* JERRY_BUILTIN_BIGINT */ +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR, "Argument 'this' is not an async generator object") +ECMA_ERROR_DEF (ECMA_ERR_CLASS_EXTENDS_NOT_CONSTRUCTOR, "Class extends value is not a constructor or null") +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW, "Generator functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_REGEXP +ECMA_ERROR_DEF (ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL, + "Return value of 'exec' must be an object or null") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER, + "Start offset is outside the bounds of the buffer") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER, "Argument 'this' is not a SharedArrayBuffer object") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +ECMA_ERROR_DEF (ECMA_ERR_CLASS_CONSTRUCTOR_NEW, "Class constructor cannot be invoked without 'new'") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP, "Incorrect value is returned by a Proxy 'get' trap") +ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP, "Incorrect value is returned by a Proxy 'set' trap") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE, "Prototype property of a class is non-configurable") +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_PUSHING_TOO_HIGH_ELEMENT, "Pushing element over 2**53-1 length is disallowed") +#endif /* JERRY_BUILTIN_ARRAY */ +ECMA_ERROR_DEF (ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED, + "The requested property update cannot be performed") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_CONFIGURABLE_KEYS, + "Trap result did not include all configurable keys") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_TARGET_NOT_EXTENSIBLE, "Trap returned truish for target is not extensible") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_NUMBER +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_NUMBER, "Argument 'this' is not a number or a Number object") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_STRING +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_STRING_OBJECT, "Argument 'this' is not a string or a String object") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER_OBJECT, + "Argument 'this' is not an SharedArrayBuffer object") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ASYNC_ARROW_FUNCTIONS_INVOKE_WITH_NEW, "Async arrow functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_ARRAY +ECMA_ERROR_DEF (ECMA_ERR_UNSHIFT_TOO_HIGH, "Unshift elements over 2**53-1 length is disallowed") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_NON_CONFIGURABLE_KEYS, + "Trap result did not include all non-configurable keys") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_ASYNC_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW, + "Async generator functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_REFLECT +ECMA_ERROR_DEF (ECMA_ERR_REFLECT_EXPECTS_AN_OBJECT_AS_SECOND_ARGUMENT, + "Reflect.construct expects an object as second argument") +#endif /* JERRY_BUILTIN_REFLECT */ +#if JERRY_ERROR_MESSAGES +ECMA_ERROR_DEF (ECMA_ERR_SCRIPT_GLOBAL_FUNCTIONS_INVOKE_WITH_NEW, + "Script (global) functions cannot be invoked with 'new'") +#endif /* JERRY_ERROR_MESSAGES */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_CREATE_PROXY, "Cannot create Proxy with a non-object target or handler") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED, + "Derived constructors may only return object or undefined") +#if JERRY_SNAPSHOT_EXEC +ECMA_ERROR_DEF (ECMA_ERR_INVALID_SNAPSHOT_VERSION_OR_FEATURES, + "Invalid snapshot version or unsupported features present") +#endif /* JERRY_SNAPSHOT_EXEC */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_TYPEDARRAY_SMALLER_THAN_FILTER_CALL_RESULT, + "Constructed TypedArray is smaller than filter call result") +ECMA_ERROR_DEF (ECMA_ERR_DERIVED_ARRAY_BUFFER_CTOR_BUFFER_TOO_SMALL, + "Derived ArrayBuffer constructor created a too small buffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_EXTENSIBILITY, + "Trap result does not reflect extensibility of Proxy target") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_EXTRA_KEYS_FOR_A_NON_EXTENSIBLE_TARGET, + "Trap returned extra keys for a non-extensible Proxy target") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_ARRAY_BUFFER_RETURNED_THIS_FROM_CONSTRUCTOR, + "ArrayBuffer subclass returned this from species constructor") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATAVIEW +ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_BUFFER_NOT_ARRAY_OR_SHARED_BUFFER, + "Argument 'buffer' is not an ArrayBuffer or SharedArrayBuffer") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_INEXTENSIBILITY, + "Trap result does not reflect inextensibility of Proxy target") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_TYPEDARRAY_INTRINSTIC_CALLED_BY_NEW_EXPRESSION, + "TypedArray intrinstic cannot be called by a 'new' expression") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +ECMA_ERROR_DEF (ECMA_ERR_CONTENTTYPE_RETURNED_TYPEDARRAY_NOT_MATCH_SOURCE, + "TypedArray returned by [[ContentType]] does not match source") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT +ECMA_ERROR_DEF (ECMA_ERR_ALLOCATE_BIGINT_STRING, "Cannot allocate memory for a string representation of a BigInt value") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED, + "Target object is non-extensible and trap returned different prototype") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET, + "Trap returned truish for adding property to the non-extensible target") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT, + "Cannot read private member to an object whose class did not declare it") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE, + "Given property is a non-configurable data property on the proxy target") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT, + "Cannot write private member to an object whose class did not declare it") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE, + "Trap returned falsish for property but the proxy target is not extensible") +ECMA_ERROR_DEF (ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER, + "Property of a Proxy is non-configurable and does not have a getter function") +ECMA_ERROR_DEF (ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER, + "The property of a Proxy target is a non configurable accessor without a setter") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_LET_CONST_NOT_INITIALIZED, + "Variables declared by let/const must be initialized before reading their value") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_PROPERTY_NON_CONFIGURABLE, + "Trap returned truish for property which is non-configurable in the proxy target") +ECMA_ERROR_DEF (ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE, + "Proxy target is non-extensible, but the trap did not return its actual prototype") +ECMA_ERROR_DEF (ECMA_ERR_TRAP_FALSISH_PROPERTY_NON_CONFIGURABLE, + "Trap returned falsish for property which exists in the proxy target as non-configurable") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS, + "Must call super constructor in derived class before accessing 'this' or returning from it") +#if JERRY_BUILTIN_PROXY +ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY, + "Trap returned truish for defining non-configurable property which is non-existent in the target") +ECMA_ERROR_DEF ( + ECMA_ERR_TRAP_TRUISH_ADD_PROPERTY_INCOMPATIBLE_OTHER_PROP, + "Trap returned truish for adding property that is incompatible with the existing property in the target") +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_ERROR_DEF (ECMA_ERR_CANNOT_ACCESS_CALLER_CALLE_ARGUMENTS, + "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the " + "arguments objects for calls to them") diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.ini b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.ini new file mode 100644 index 00000000..c2d7031a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-error-messages.ini @@ -0,0 +1,331 @@ +# Copyright JS Foundation and other contributors, http://js.foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[ECMA_ERROR_MESSAGES] + +ECMA_ERR_CANNOT_ACCESS_CALLER_CALLE_ARGUMENTS = "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them" +ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE = "'reject' parameter must be callable" +ECMA_ERR_PARAMETER_RESOLVE_MUST_BE_CALLABLE = "'resolve' parameter must be callable" +ECMA_ERR_PROMISE_RESOLVE_ITSELF = "A promise cannot be resolved with itself" +ECMA_ERR_ACCESSOR_WRITABLE = "Accessors cannot be writable" +ECMA_ERR_ARGUMENT_BUFFER_NOT_ARRAY_OR_SHARED_BUFFER = "Argument 'buffer' is not an ArrayBuffer or SharedArrayBuffer" +ECMA_ERR_ARGUMENT_BUFFER_NOT_OBJECT = "Argument 'buffer' is not an object" +ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT = "Argument 'this' is not an ArrayBuffer object" +ECMA_ERR_ARGUMENT_THIS_NOT_BOOLEAN_OBJECT = "Argument 'this' is not a Boolean object" +ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT = "Argument 'this' is not a Date object" +ECMA_ERR_ARGUMENT_THIS_NOT_PROMISE = "Argument 'this' is not a Promise" +ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER = "Argument 'this' is not a SharedArrayBuffer object" +ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY = "Argument 'this' is not a TypedArray" +ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR = "Argument 'this' is not a constructor" +ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION = "Argument 'this' is not a function" +ECMA_ERR_ARGUMENT_THIS_NOT_GENERATOR_OBJECT = "Argument 'this' is not a generator object" +ECMA_ERR_ARGUMENT_THIS_NOT_NUMBER = "Argument 'this' is not a number or a Number object" +ECMA_ERR_ARGUMENT_THIS_NOT_STRING_OBJECT = "Argument 'this' is not a string or a String object" +ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP = "Argument 'this' is not a valid RegExp" +ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP_OBJECT = "Argument 'this' is not a valid RegExp object" +ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER_OBJECT = "Argument 'this' is not an SharedArrayBuffer object" +ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR = "Argument 'this' is not an async generator object" +ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR = "Argument 'this' is not an iterator" +ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT = "Argument 'this' is not an object" +ECMA_ERR_ARGUMENT_THIS_NOT_SYMBOL = "Argument 'this' must be a Symbol" +ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT = "Argument cannot be converted to an object" +ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER = "Argument is not SharedArrayBuffer" +ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER = "Argument is not an ArrayBuffer" +ECMA_ERR_ARGUMENT_NOT_SUPPORTED = "Argument is not supported" +ECMA_ERR_ARRAY_BUFFER_DETACHED = "ArrayBuffer has already been detached" +ECMA_ERR_ARRAY_BUFFER_RETURNED_THIS_FROM_CONSTRUCTOR = "ArrayBuffer subclass returned this from species constructor" +ECMA_ERR_BIGINT_SERIALIZED = "BigInt cannot be serialized" +ECMA_ERR_BIGINT_ZERO_DIVISION = "BigInt division by zero" +ECMA_ERR_BIGINT_FUNCTION_NOT_CONSTRUCTOR = "BigInt function is not a constructor" +ECMA_ERR_BIGINT_VALUE_EXCPECTED = "BigInt value expected" +ECMA_ERR_BINDING_CANNOT_SET = "Binding cannot be set" +ECMA_ERR_BINDING_NOT_EXIST_OR_UNINITIALIZED = "Binding does not exist or is uninitialised" +ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR = "Built-in routines have no constructor" +ECMA_ERR_CALLBACK_RESULT_NOT_MODULE = "Callback result must be a module" +ECMA_ERR_ALLOCATE_ARRAY_BUFFER = "Cannot allocate memory for ArrayBuffer" +ECMA_ERR_ALLOCATE_BIGINT_VALUE = "Cannot allocate memory for a BigInt value" +ECMA_ERR_ALLOCATE_BIGINT_STRING = "Cannot allocate memory for a string representation of a BigInt value" +ECMA_ERR_CONVERT_BIGINT_TO_NUMBER = "Cannot convert a BigInt value to a number" +ECMA_ERR_CONVERT_SYMBOL_TO_NUMBER = "Cannot convert a Symbol value to a number" +ECMA_ERR_CONVERT_SYMBOL_TO_STRING = "Cannot convert a Symbol value to a string" +ECMA_ERR_CANNOT_CREATE_PROXY = "Cannot create Proxy with a non-object target or handler" +ECMA_ERR_INVOKE_NULLABLE_SUPER_METHOD = "Cannot invoke nullable super method" +ECMA_ERR_LINK_TO_MODULE_IN_ERROR_STATE = "Cannot link to a module which is in error state" +ECMA_ERR_SET_EXTENSIBLE_PROPERTY = "Cannot set [[Extensible]] property of object" +ECMA_ERR_SET_PROTOTYPE = "Cannot set [[Prototype]]" +ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW = "Class constructor requires 'new'" +ECMA_ERR_CLASS_EXTENDS_NOT_CONSTRUCTOR = "Class extends value is not a constructor or null" +ECMA_ERR_COMPARE_FUNC_NOT_CALLABLE = "Compare function is not callable" +ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED = "Constant bindings cannot be reassigned" +ECMA_ERR_TYPEDARRAY_SMALLER_THAN_FILTER_CALL_RESULT = "Constructed TypedArray is smaller than filter call result" +ECMA_ERR_CONSTRUCTED_OBJECT_IS_NOT_TYPEDARRAY = "Constructed object is not TypedArray" +ECMA_ERR_CONSTRUCTOR_ARRAYBUFFER_REQUIRES_NEW = "Constructor ArrayBuffer requires 'new'" +ECMA_ERR_CONSTRUCTOR_BIGINT64_ARRAY_REQUIRES_NEW = "Constructor BigInt64Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_BIG_UINT64_ARRAY_REQUIRES_NEW = "Constructor BigUInt64Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_DATAVIEW_REQUIRES_NEW = "Constructor DataView requires 'new'" +ECMA_ERR_CONSTRUCTOR_FLOAT32_ARRAY_REQUIRES_NEW = "Constructor Float32Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_FLOAT64_ARRAY_REQUIRES_NEW = "Constructor Float64Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_INT16_ARRAY_REQUIRES_NEW = "Constructor Int16Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_INT32_ARRAY_REQUIRES_NEW = "Constructor Int32Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_INT8_ARRAY_REQUIRES_NEW = "Constructor Int8Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_MAP_REQUIRES_NEW = "Constructor Map requires 'new'" +ECMA_ERR_CONSTRUCTOR_PROMISE_REQUIRES_NEW = "Constructor Promise requires 'new'" +ECMA_ERR_CONSTRUCTOR_PROXY_REQUIRES_NEW = "Constructor Proxy requires 'new'" +ECMA_ERR_CONSTRUCTOR_SET_REQUIRES_NEW = "Constructor Set requires 'new'" +ECMA_ERR_CONSTRUCTOR_SHAREDARRAYBUFFER_REQUIRES_NEW = "Constructor SharedArrayBuffer requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT16_ARRAY_REQUIRES_NEW = "Constructor Uint16Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW = "Constructor Uint32Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT8_ARRAY_REQUIRES_NEW = "Constructor Uint8Array requires 'new'" +ECMA_ERR_CONSTRUCTOR_UINT8_CLAMPED_ARRAY_REQUIRES_NEW = "Constructor Uint8ClampedArray requires 'new'" +ECMA_ERR_CONSTRUCTOR_WEAKMAP_REQUIRES_NEW = "Constructor WeakMap requires 'new'" +ECMA_ERR_CONSTRUCTOR_WEAKREF_REQUIRES_NEW = "Constructor WeakRef requires 'new'." +ECMA_ERR_CONSTRUCTOR_WEAKSET_REQUIRES_NEW = "Constructor WeakSet requires 'new'" +ECMA_ERR_CONSTRUCTOR_NOT_AN_OBJECT = "Constructor must be an object" +ECMA_ERR_CONTAINER_IS_NOT_A_CONTAINER_OBJECT = "Container is not a container object." +ECMA_ERR_CONTAINER_IS_NOT_AN_OBJECT = "Container is not an object." +ECMA_ERR_DATE_MUST_BE_A_FINITE_NUMBER = "Date must be a finite number" +ECMA_ERR_DERIVED_ARRAY_BUFFER_CTOR_BUFFER_TOO_SMALL = "Derived ArrayBuffer constructor created a too small buffer" +ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED = "Derived constructors may only return object or undefined" +ECMA_ERR_INVALID_CODE_POINT_ERROR = "Error: Invalid code point" +ECMA_ERR_EXPECTED_A_DATAVIEW_OBJECT = "Expected a DataView object" +ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY = "Expected a configurable property" +ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT = "Expected a function object" +ECMA_ERR_EXPECTED_AN_ARRAYBUFFER = "Expected an ArrayBuffer" +ECMA_ERR_EXPECTED_AN_OBJECT = "Expected an object" +ECMA_ERR_FIRST_ARGUMENT_IS_NOT_A_REALM = "First argument is not a realm" +ECMA_ERR_FIRST_PARAMETER_MUST_BE_CALLABLE = "First parameter must be callable" +ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE = "Fraction digits must be between 0 and 100" +ECMA_ERR_FUNCTION_ADD_ORSET_IS_NOT_CALLABLE = "Function add/set is not callable" +ECMA_ERR_FUNCTION_INDEX_IS_HIGHER_THAN_MAXIMUM = "Function index is higher than maximum" +ECMA_ERR_FUNCTION_PROTOTYPE_NOT_A_CONSTRUCTOR = "Function.prototype is not a constructor" +ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION = "Generator is currently under execution" +ECMA_ERR_GETTER_IS_NOT_CALLABLE = "Getter is not callable" +ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE = "Given property is a non-configurable data property on the proxy target" +ECMA_ERR_HANDLER_CANNOT_BE_NULL = "Handler cannot be null" +ECMA_ERR_IMPORTED_BINDING_SHADOWS_LOCAL_VARIABLE = "Imported binding shadows local variable" +ECMA_ERR_INCOMPATIBLE_TYPEDARRAY_TYPES = "Incompatible TypedArray types" +ECMA_ERR_INCORRECT_TYPE_FOR_TYPEDARRAY = "Incorrect type for TypedArray" +ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP = "Incorrect value is returned by a Proxy 'get' trap" +ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP = "Incorrect value is returned by a Proxy 'set' trap" +ECMA_ERR_INFINITY_OR_NAN_CANNOT_BE_CONVERTED_TO_BIGINT = "Infinity or NaN cannot be converted to BigInt" +ECMA_ERR_INITIAL_VALUE_CANNOT_BE_UNDEFINED = "Initial value cannot be undefined" +ECMA_ERR_INVALID_ARRAYBUFFER_LENGTH = "Invalid ArrayBuffer length" +ECMA_ERR_INVALID_JSON_FORMAT = "Invalid JSON format" +ECMA_ERR_INVALID_REGEXP_FLAGS = "Invalid RegExp flags" +ECMA_ERR_INVALID_SHARED_ARRAYBUFFER_LENGTH = "Invalid Shared ArrayBuffer length" +ECMA_ERR_INVALID_TYPEDARRAY_LENGTH = "Invalid TypedArray length" +ECMA_ERR_INVALID_UTF8_CHARACTER = "Invalid UTF8 character" +ECMA_ERR_INVALID_UTF8_CODEPOINT = "Invalid UTF8 codepoint" +ECMA_ERR_INVALID_UTF8_STRING = "Invalid UTF8 string" +ECMA_ERR_INVALID_ENCODING = "Invalid encoding" +ECMA_ERR_INVALID_ARGUMENT = "Invalid argument" +ECMA_ERR_INVALID_ARGUMENT_TYPE_IN_TOPRIMITIVE = "Invalid argument type in toPrimitive" +ECMA_ERR_INVALID_CAPABILITY = "Invalid capability" +ECMA_ERR_INVALID_CHARACTER_CLASS = "Invalid character class" +ECMA_ERR_INVALID_CODE_POINT = "Invalid code point" +ECMA_ERR_INVALID_CONTAINER_TYPE = "Invalid container type" +ECMA_ERR_INVALID_CONTROL_ESCAPE_SEQUENCE = "Invalid control escape sequence" +ECMA_ERR_INVALID_COUNT_VALUE = "Invalid count value" +ECMA_ERR_INVALID_ESCAPE = "Invalid escape" +ECMA_ERR_INVALID_ESCAPE_SEQUENCE = "Invalid escape sequence" +ECMA_ERR_INVALID_GROUP = "Invalid group" +ECMA_ERR_INVALID_HEX_ESCAPE_SEQUENCE = "Invalid hex escape sequence" +ECMA_ERR_INVALID_HEXADECIMAL_VALUE = "Invalid hexadecimal value" +ECMA_ERR_INVALID_LENGTH = "Invalid length" +ECMA_ERR_INVALID_NEW_ARRAY_LENGTH = "Invalid new Array length" +ECMA_ERR_INVALID_OFFSET = "Invalid offset" +ECMA_ERR_INVALID_OR_OUT_OF_RANGE_INDEX = "Invalid or out-of-range index" +ECMA_ERR_INVALID_QUANTIFIER = "Invalid quantifier" +ECMA_ERR_INVALID_RANGE_OF_INDEX = "Invalid range of index" +ECMA_ERR_INVALID_SCOPE_CHAIN_INDEX_FOR_EVAL = "Invalid scope chain index for eval" +ECMA_ERR_INVALID_SPECIES_CONSTRUCTOR = "Invalid species constructor" +ECMA_ERR_INVALID_STRING_ = "Invalid string length" +ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE = "Invalid unicode escape sequence" +ECMA_ERR_ITERATOR_NEXT_IS_NOT_CALLABLE = "Iterator 'next' is not callable" +ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT = "Iterator 'return' result is not object" +ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE = "Iterator 'throw' is not available" +ECMA_ERR_ITERATOR_IS_NOT_AN_OBJECT = "Iterator is not an object" +ECMA_ERR_ITERATOR_IS_NOT_CALLABLE = "Iterator is not callable" +ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT = "Iterator result is not an object" +ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT = "Iterator value is not an object" +ECMA_ERR_JSON_STRING_PARSE_ERROR = "JSON string parse error" +ECMA_ERR_JSON_STRINGIFY_ERROR = "JSON stringify error" +ECMA_ERR_KEY_MUST_BE_AN_OBJECT = "Key must be an object" +ECMA_ERR_LONE_QUANTIFIER_BRACKET = "Lone quantifier bracket" +ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED = "Maximum TypedArray size is reached" +ECMA_ERR_MAXIMUM_STRING_LENGTH_IS_REACHED = "Maximum string length is reached" +ECMA_ERR_MISSING_ARRAY_ELEMENT = "Missing Array element" +ECMA_ERR_MODULE_CANNOT_BE_INSTANTIATED = "Module cannot be instantiated" +ECMA_ERR_MODULE_EXPORTS_MUST_BE_STRING_VALUES = "Module exports must be string values" +ECMA_ERR_MODULE_EXPORTS_MUST_BE_VALID_IDENTIFIERS = "Module exports must be valid identifiers" +ECMA_ERR_MODULE_IS_IN_ERROR_STATE = "Module is in error state" +ECMA_ERR_MODULE_MUST_BE_IN_LINKED_STATE = "Module must be in linked state" +ECMA_ERR_MODULE_MUST_BE_IN_UNLINKED_STATE = "Module must be in unlinked state" +ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS = "Must call super constructor in derived class before accessing 'this' or returning from it" +ECMA_ERR_NAMESPACE_OBJECT_IS_NOT_AVAILABLE = "Namespace object is not available" +ECMA_ERR_NEGATIVE_EXPONENT_IS_NOT_ALLOWED_FOR_BIGINTS = "Negative exponent is not allowed for BigInts" +ECMA_ERR_NO_SOURCE_ARGUMENT = "No source argument" +ECMA_ERR_NOTHING_TO_REPEAT = "Nothing to repeat" +ECMA_ERR_OBJECT_CANNOT_BE_FROZEN = "Object cannot be frozen" +ECMA_ERR_OBJECT_CANNOT_BE_SEALED = "Object cannot be sealed" +ECMA_ERR_OBJECT_EXPECTED = "Object expected" +ECMA_ERR_OBJECT_IS_NOT_A_TYPEDARRAY = "Object is not a TypedArray" +ECMA_ERR_ONLY_INTEGER_NUMBERS_CAN_BE_CONVERTED_TO_BIGINT = "Only integer numbers can be converted to BigInt" +ECMA_ERR_OPERATOR_DELETE_RETURNED_FALSE_IN_STRICT_MODE = "Operator delete returned false in strict mode" +ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM = "Passed argument is not a realm" +ECMA_ERR_PRECISION_DIGITS_MUST_BE_BETWEEN_IN_RANGE = "Precision digits must be between 1 and 100" +ECMA_ERR_PROMISE_ALL_REMAINING_ELEMENTS_LIMIT_REACHED = "Promise.all remaining elements limit reached" +ECMA_ERR_PROPERTY_PROTOTYPE_IS_NOT_AN_OBJECT = "Property 'prototype' is not an object or null" +ECMA_ERR_PROPERTY_NAME_IS_NEITHER_SYMBOL_NOR_STRING = "Property name is neither Symbol nor string" +ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER = "Property of a Proxy is non-configurable and does not have a getter function" +ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID = "Prototype from revoked Proxy is invalid" +ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL = "Prototype is neither object nor null" +ECMA_ERR_PROXY_HANDLER_IS_NULL_FOR_ISARRAY_OPERATION = "Proxy handler is null for 'isArray' operation" +ECMA_ERR_PROXY_IS_NOT_SUPPORTED = "Proxy is not supported" +ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE = "Proxy target is non-extensible, but the trap did not return its actual prototype" +ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH = "Proxy trap returned falsish" +ECMA_ERR_PUSHING_TOO_HIGH_ELEMENT = "Pushing element over 2**53-1 length is disallowed" +ECMA_ERR_MIN_GREATER_THAN_MAX = "Quantifier error: min > max" +ECMA_ERR_RADIX_IS_OUT_OF_RANGE = "Radix must be between 2 and 36" +ECMA_ERR_RANGE_OUT_OF_ORDER_IN_CHARACTER_CLASS = "Range out of order in character class" +ECMA_ERR_REALM_IS_NOT_AVAILABLE = "Realm is not available" +ECMA_ERR_REALMS_ARE_DISABLED = "Realms are disabled" +ECMA_ERR_REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE = "Reduce of empty Array with no initial value" +ECMA_ERR_REFLECT_EXPECTS_AN_OBJECT_AS_SECOND_ARGUMENT = "Reflect.construct expects an object as second argument" +ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG = "RegExp argument should have global flag" +ECMA_ERR_REGEXP_IS_NOT_SUPPORTED = "RegExp is not supported" +ECMA_ERR_REJECT_MUST_BE_UNDEFINED = "Reject must be undefined" +ECMA_ERR_REQUEST_IS_NOT_AVAILABLE = "Request is not available" +ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE = "Resolve method must be callable" +ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED = "Resolve must be undefined" +ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID = "Result of [[DefaultValue]] is invalid" +ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT = "Return value is not an ArrayBuffer object" +ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL = "Return value of 'exec' must be an object or null" +ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT = "Right value of 'in' must be an object" +ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT = "Right value of 'instanceof' must be an object" +ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP = "Search string can't be of type: RegExp" +ECMA_ERR_SECOND_ARGUMENT_MUST_BE_AN_OBJECT = "Second argument must be an object" +ECMA_ERR_SPECIES_MUST_BE_A_CONSTRUCTOR = "Species must be a constructor" +ECMA_ERR_STACK_LIMIT_EXCEEDED = "Stack limit exceeded" +ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER = "Start offset is outside the bounds of the buffer" +ECMA_ERR_STATIC_SNAPSHOTS_ARE_NOT_ENABLED = "Static snapshots are not enabled" +ECMA_ERR_STATIC_SNAPSHOTS_CANNOT_BE_COPIED_INTO_MEMORY = "Static snapshots cannot be copied into memory" +ECMA_ERR_STRING_CANNOT_BE_CONVERTED_TO_BIGINT_VALUE = "String cannot be converted to BigInt value" +ECMA_ERR_SUPER_BINDING_MUST_BE_A_CONSTRUCTOR = "Super binding must be a constructor" +ECMA_ERR_SUPER_CONSTRUCTOR_MAY_ONLY_BE_CALLED_ONCE = "Super constructor may only be called once" +ECMA_ERR_SYMBOL_IS_NOT_A_CONSTRUCTOR = "Symbol is not a constructor" +ECMA_ERR_TARGET_IS_NOT_OBJECT = "Target is not Object" +ECMA_ERR_TARGET_IS_NOT_WEAKREF = "Target is not weakRef" +ECMA_ERR_TARGET_NOT_EXTENSIBLE = "Target not extensible" +ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED = "Target object is non-extensible and trap returned different prototype" +ECMA_ERR_THE_MAPFN_ARGUMENT_IS_NOT_CALLABLE = "The 'mapfn' argument is not callable" +ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL = "The given argument is not a Symbol" +ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER = "The property of a Proxy target is a non configurable accessor without a setter" +ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED = "The requested property update cannot be performed" +ECMA_ERR_THE_STRUCTURE_IS_CYCLICAL = "The structure is cyclical" +ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE = "The two descriptors are incompatible" +ECMA_ERR_TOO_MANY_ARGUMENTS_DECLARED_FOR_FUNCTION_APPLY = "Too many arguments declared for Function.apply" +ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED = "Trap is neither an object nor undefined" +ECMA_ERR_TRAP_MUST_RETURN_WITH_AN_OBJECT = "Trap must return with an object" +ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_CONFIGURABLE_KEYS = "Trap result did not include all configurable keys" +ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_NON_CONFIGURABLE_KEYS = "Trap result did not include all non-configurable keys" +ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_EXTENSIBILITY = "Trap result does not reflect extensibility of Proxy target" +ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_INEXTENSIBILITY = "Trap result does not reflect inextensibility of Proxy target" +ECMA_ERR_TRAP_EXTRA_KEYS_FOR_A_NON_EXTENSIBLE_TARGET = "Trap returned extra keys for a non-extensible Proxy target" +ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE = "Trap returned falsish for property but the proxy target is not extensible" +ECMA_ERR_TRAP_FALSISH_PROPERTY_NON_CONFIGURABLE = "Trap returned falsish for property which exists in the proxy target as non-configurable" +ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL = "Trap returned neither object nor null" +ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET = "Trap returned truish for adding property to the non-extensible target" +ECMA_ERR_TRAP_TRUISH_ADD_PROPERTY_INCOMPATIBLE_OTHER_PROP = "Trap returned truish for adding property that is incompatible with the existing property in the target" +ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY = "Trap returned truish for defining non-configurable property which is non-existent in the target" +ECMA_ERR_TRAP_TRUISH_PROPERTY_NON_CONFIGURABLE = "Trap returned truish for property which is non-configurable in the proxy target" +ECMA_ERR_TRAP_TRUISH_TARGET_NOT_EXTENSIBLE = "Trap returned truish for target is not extensible" +ECMA_ERR_TRAP_WITH_DUPLICATED_ENTRIES = "Trap returned with duplicated entries" +ECMA_ERR_TYPEDARRAY_INTRINSTIC_CALLED_BY_NEW_EXPRESSION = "TypedArray intrinstic cannot be called by a 'new' expression" +ECMA_ERR_TYPEDARRAY_INTRINSTIC_DIRECTLY_CALLED = "TypedArray intrinstic cannot be directly called" +ECMA_ERR_CONTENTTYPE_RETURNED_TYPEDARRAY_NOT_MATCH_SOURCE = "TypedArray returned by [[ContentType]] does not match source" +ECMA_ERR_UNARY_PLUS_IS_NOT_ALLOWED_FOR_BIGINTS = "Unary plus is not allowed for BigInts" +ECMA_ERR_UNDEFINED_REFERENCE = "Undefined reference" +ECMA_ERR_UNEXPECTED_END_OF_PATTERN = "Unexpected end of pattern" +ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING = "Unicode surrogate pair missing" +ECMA_ERR_UNMATCHED_CLOSE_BRACKET = "Unmatched close bracket" +ECMA_ERR_UNSHIFT_TOO_HIGH = "Unshift elements over 2**53-1 length is disallowed" +ECMA_ERR_UNSIGNED_RIGHT_SHIFT_IS_NOT_ALLOWED_FOR_BIGINTS = "Unsigned right shift is not allowed for BigInts" +ECMA_ERR_UNSUPPORTED_BINARY_OPERATION = "Unsupported binary operation" +ECMA_ERR_UNSUPPORTED_CONTAINER_OPERATION = "Unsupported container operation" +ECMA_ERR_UNSUPPORTED_SNAPSHOT_EXEC_FLAGS_ARE_SPECIFIED = "Unsupported snapshot exec flags are specified" +ECMA_ERR_UNTERMINATED_CHARACTER_CLASS = "Unterminated character class" +ECMA_ERR_UNTERMINATED_GROUP = "Unterminated group" +ECMA_ERR_VALUE_CANNOT_BE_CONVERTED_TO_BIGINT = "Value cannot be converted to BigInt" +ECMA_ERR_VALUE_FOR_CLASS_HERITAGE_IS_NOT_A_CONSTRUCTOR = "Value for class heritage is not a constructor" +ECMA_ERR_VALUE_RECEIVED_BY_FOR_ASYNC_OF_IS_NOT_OBJECT = "Value received by for-async-of is not object" +ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT = "Value received by yield* is not object" +ECMA_ERR_WEAKREF_TARGET_MUST_BE_AN_OBJECT = "WeakRef target must be an object" +ECMA_ERR_METHOD_RETURN_IS_NOT_CALLABLE = "method 'return' is not callable" +ECMA_ERR_VALUE_MSG = "Argument cannot be marked as error" +ECMA_ERR_WRONG_ARGS_MSG = "This type of argument is not allowed" +ECMA_ERR_PARSER_NOT_SUPPORTED = "Source code parsing is disabled" +ECMA_ERR_JSON_NOT_SUPPORTED = "JSON support is disabled" +ECMA_ERR_TYPED_ARRAY_NOT_SUPPORTED = "TypedArray support is disabled" +ECMA_ERR_SHARED_ARRAYBUFFER_NOT_SUPPORTED = "SharedArrayBuffer support is disabled" +ECMA_ERR_DATA_VIEW_NOT_SUPPORTED = "DataView support is disabled" +ECMA_ERR_BIGINT_NOT_SUPPORTED = "BigInt support is disabled" +ECMA_ERR_CONTAINER_NOT_SUPPORTED = "Container support is disabled" +ECMA_ERR_NOT_MODULE = "Argument is not a module" +ECMA_ERR_UNKNOWN_EXPORT = "Native module export not found" +ECMA_ERR_MODULE_NOT_SUPPORTED = "Module support is disabled" +ECMA_ERR_CALLBACK_IS_NOT_CALLABLE = "Callback function is not callable" +ECMA_ERR_ARRAYBUFFER_IS_DETACHED = "ArrayBuffer has been detached" +ECMA_ERR_CANNOT_CONVERT_TO_OBJECT = "Cannot convert undefined or null to object" +ECMA_ERR_CLASS_IS_NON_CONFIGURABLE = "Prototype property of a class is non-configurable" +ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT = "Argument is not an object" +ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY = "Argument is not a Proxy object" +ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR = "Target is not a constructor" +ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP = "Argument 'this' is not a RegExp object" +ECMA_ERR_INVALID_ARRAY_LENGTH = "Invalid Array length" +ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED = "Local variable is redeclared" +ECMA_ERR_EXPECTED_A_FUNCTION = "Expected a function" +ECMA_ERR_CLASS_CONSTRUCTOR_NEW = "Class constructor cannot be invoked without 'new'" +ECMA_ERR_LET_CONST_NOT_INITIALIZED = "Variables declared by let/const must be initialized before reading their value" +ECMA_ERR_MAXIMUM_SNAPSHOT_SIZE = "Maximum snapshot size reached" +ECMA_ERR_REGULAR_EXPRESSION_NOT_SUPPORTED = "Regular expression literals are not supported" +ECMA_ERR_SNAPSHOT_BUFFER_SMALL = "Snapshot buffer too small" +ECMA_ERR_SNAPSHOT_UNSUPPORTED_COMPILED_CODE = "Unsupported compiled code" +ECMA_ERR_SNAPSHOT_FLAG_NOT_SUPPORTED = "Unsupported generate snapshot flags specified" +ECMA_ERR_SNAPSHOT_SAVE_DISABLED = "Snapshot generation is disabled" +ECMA_ERR_SNAPSHOT_EXEC_DISABLED = "Snapshot execution is disabled" +ECMA_ERR_CANNOT_ALLOCATE_MEMORY_LITERALS = "Cannot allocate memory for literals" +ECMA_ERR_TAGGED_TEMPLATE_LITERALS = "Unsupported feature: tagged template literals" +ECMA_ERR_CONTAINER_NEEDED = "Value is not a Container or Iterator" +ECMA_ERR_INCORRECT_TYPE_CALL = "Operator called on incorrect container type" +ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL = "Invalid type for constructor call" +ECMA_ERR_SCRIPT_GLOBAL_FUNCTIONS_INVOKE_WITH_NEW = "Script (global) functions cannot be invoked with 'new'" +ECMA_ERR_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW = "Generator functions cannot be invoked with 'new'" +ECMA_ERR_ASYNC_FUNCTIONS_INVOKE_WITH_NEW = "Async functions cannot be invoked with 'new'" +ECMA_ERR_ASYNC_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW = "Async generator functions cannot be invoked with 'new'" +ECMA_ERR_ACCESSOR_FUNCTIONS_INVOKE_WITH_NEW = "Accessor functions cannot be invoked with 'new'" +ECMA_ERR_METHODS_INVOKE_WITH_NEW = "Methods cannot be invoked with 'new'" +ECMA_ERR_ARROW_FUNCTIONS_INVOKE_WITH_NEW = "Arrow functions cannot be invoked with 'new'" +ECMA_ERR_ASYNC_ARROW_FUNCTIONS_INVOKE_WITH_NEW = "Async arrow functions cannot be invoked with 'new'" +ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR = "Proxy target is not a constructor" +ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED = "Maximum call stack size exceeded" +ECMA_ERR_INVALID_SNAPSHOT_FORMAT = "Invalid snapshot format" +ECMA_ERR_INVALID_SNAPSHOT_VERSION_OR_FEATURES = "Invalid snapshot version or unsupported features present" +ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT = "Receiver must be an object" +ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE = "Cannot declare same private field twice" +ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT = "Cannot write private member to an object whose class did not declare it" +ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE = "Private method is not writable" +ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER = "Private field was defined without a setter" +ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT = "Cannot read private member to an object whose class did not declare it" +ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER = "Private field was defined without a getter" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.cpp new file mode 100644 index 00000000..7592fe82 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.cpp @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-errors.h" + +#if JERRY_ERROR_MESSAGES +/** + * Struct to store ecma error message with its size. + */ +typedef struct +{ + char *text; /* Text of ecma error message. */ + uint8_t size; /* Size of ecma error message. */ +} ecma_error_message_t; + +/* Error message texts with size. */ +static ecma_error_message_t ecma_error_messages[] JERRY_ATTR_CONST_DATA = { + { "", 0 }, /* ECMA_ERR_EMPTY */ +/** @cond doxygen_suppress */ +#define ECMA_ERROR_DEF(id, string) { string, sizeof (string) - 1 }, +#include "ecma-error-messages.inc.h" +#undef ECMA_ERROR_DEF + /** @endcond */ +}; +#endif /* JERRY_ERROR_MESSAGES */ + +/** + * Get specified ecma error as zero-terminated string + * + * @return pointer to zero-terminated ecma error + */ +const char * +ecma_get_error_msg (ecma_error_msg_t id) /**< ecma error id */ +{ + JERRY_ASSERT (id != ECMA_IS_VALID_CONSTRUCTOR); + +#if JERRY_ERROR_MESSAGES + return ecma_error_messages[id].text; +#else /* !JERRY_ERROR_MESSAGES */ + return NULL; +#endif /* JERRY_ERROR_MESSAGES */ +} /* ecma_get_error_msg */ + +/** + * Get size of specified ecma error + * + * @return size in bytes + */ +lit_utf8_size_t +ecma_get_error_size (ecma_error_msg_t id) /**< ecma error id */ +{ + JERRY_ASSERT (id != ECMA_IS_VALID_CONSTRUCTOR); + +#if JERRY_ERROR_MESSAGES + return ecma_error_messages[id].size; +#else /* !JERRY_ERROR_MESSAGES */ + return 0; +#endif /* JERRY_ERROR_MESSAGES */ +} /* ecma_get_error_size */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.h new file mode 100644 index 00000000..72947e6e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-errors.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ERRORS_H +#define ECMA_ERRORS_H + +#include "lit-globals.h" + +typedef enum +{ + ECMA_ERR_EMPTY, +/** @cond doxygen_suppress */ +#if JERRY_ERROR_MESSAGES +#define ECMA_ERROR_DEF(id, ascii_zt_string) id, +#else /* !JERRY_ERROR_MESSAGES */ +#define ECMA_ERROR_DEF(id, ascii_zt_string) id = ECMA_ERR_EMPTY, +#endif /* JERRY_ERROR_MESSAGES */ +#include "ecma-error-messages.inc.h" +#undef ECMA_ERROR_DEF + /** @endcond */ + ECMA_IS_VALID_CONSTRUCTOR /* used as return value when checking constructor */ +} ecma_error_msg_t; + +const char* ecma_get_error_msg (ecma_error_msg_t id); +lit_utf8_size_t ecma_get_error_size (ecma_error_msg_t id); + +#endif /* !ECMA_ERRORS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.cpp new file mode 100644 index 00000000..1dcf3d34 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.cpp @@ -0,0 +1,144 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-extended-info.h" + +#include "ecma-helpers.h" + +#include "byte-code.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaextendedinfo Extended info + * @{ + */ + +/** + * Decodes an uint32_t number, and updates the buffer position. + * + * @return the decoded value + */ +uint32_t +ecma_extended_info_decode_vlq (uint8_t **buffer_p) /**< [in/out] target buffer */ +{ + uint8_t *source_p = *buffer_p; + uint32_t value = 0; + + do + { + source_p--; + value = (value << ECMA_EXTENDED_INFO_VLQ_SHIFT) | (*source_p & ECMA_EXTENDED_INFO_VLQ_MASK); + } while (*source_p & ECMA_EXTENDED_INFO_VLQ_CONTINUE); + + *buffer_p = source_p; + return value; +} /* ecma_extended_info_decode_vlq */ + +/** + * Encodes an uint32_t number into a buffer. + */ +void +ecma_extended_info_encode_vlq (uint8_t **buffer_p, /**< target buffer */ + uint32_t value) /**< encoded value */ +{ + uint8_t *destination_p = *buffer_p - 1; + + if (value <= ECMA_EXTENDED_INFO_VLQ_MASK) + { + *destination_p = (uint8_t) value; + *buffer_p = destination_p; + return; + } + + uint32_t length = 0; + uint32_t current_value = value >> ECMA_EXTENDED_INFO_VLQ_SHIFT; + + do + { + current_value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT; + length++; + } while (current_value > 0); + + destination_p -= length; + *buffer_p = destination_p; + + do + { + *destination_p++ = (uint8_t) (value | ECMA_EXTENDED_INFO_VLQ_CONTINUE); + value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT; + } while (value > 0); + + **buffer_p &= ECMA_EXTENDED_INFO_VLQ_MASK; +} /* ecma_extended_info_encode_vlq */ + +/** + * Gets the encoded length of a number. + * + * @return encoded length + */ +uint32_t +ecma_extended_info_get_encoded_length (uint32_t value) /**< encoded value */ +{ + uint32_t length = 0; + + do + { + value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT; + length++; + } while (value > 0); + + return length; +} /* ecma_extended_info_get_encoded_length */ + +/** + * Get the extended info from a byte code + * + * @return pointer to the extended info + */ +uint8_t * +ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO); + + ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + base_p--; + } + +#if JERRY_LINE_INFO + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + base_p--; + } +#endif /* JERRY_LINE_INFO */ + + JERRY_ASSERT (((uint8_t *) base_p)[-1] != 0); + + return ((uint8_t *) base_p) - 1; +} /* ecma_compiled_code_resolve_extended_info */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.h new file mode 100644 index 00000000..57046bd2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-extended-info.h @@ -0,0 +1,54 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_EXTENDED_INFO_H +#define ECMA_EXTENDED_INFO_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaextendedinfo Extended info + * @{ + */ + +#include "ecma-globals.h" + +/** + * Vlq encoding: flag which is set for all bytes except the last one. + */ +#define ECMA_EXTENDED_INFO_VLQ_CONTINUE 0x80 + +/** + * Vlq encoding: mask to decode the number fragment. + */ +#define ECMA_EXTENDED_INFO_VLQ_MASK 0x7f + +/** + * Vlq encoding: number of bits stored in a byte. + */ +#define ECMA_EXTENDED_INFO_VLQ_SHIFT 7 + +uint32_t ecma_extended_info_decode_vlq (uint8_t **buffer_p); +void ecma_extended_info_encode_vlq (uint8_t **buffer_p, uint32_t value); +uint32_t ecma_extended_info_get_encoded_length (uint32_t value); + +uint8_t *ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_EXTENDED_INFO_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.cpp new file mode 100644 index 00000000..ea6f380c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.cpp @@ -0,0 +1,2344 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Garbage collector implementation + */ + +#include "ecma-gc.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-container-object.h" +#include "ecma-function-object.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lcache.h" +#include "ecma-objects.h" +#include "ecma-property-hashmap.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" +#include "jrt-bit-fields.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "re-compiler.h" +#include "vm-defines.h" +#include "vm-stack.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#include "ecma-typedarray-object.h" +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-promise-object.h" + +/* TODO: Extract GC to a separate component */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmagc Garbage collector + * @{ + */ + +/* + * The garbage collector uses the reference counter + * of object: it increases the counter by one when + * the object is marked at the first time. + */ + +/** + * Get visited flag of the object. + * + * @return true - if visited + * false - otherwise + */ +static inline bool +ecma_gc_is_object_visited (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + return (object_p->type_flags_refs < ECMA_OBJECT_NON_VISITED); +} /* ecma_gc_is_object_visited */ + +/** + * Mark objects as visited starting from specified object as root + */ +static void ecma_gc_mark (ecma_object_t *object_p); + +/** + * Set visited flag of the object. + */ +static void +ecma_gc_set_object_visited (ecma_object_t *object_p) /**< object */ +{ + if (object_p->type_flags_refs >= ECMA_OBJECT_NON_VISITED) + { +#if (JERRY_GC_MARK_LIMIT != 0) + if (JERRY_CONTEXT (ecma_gc_mark_recursion_limit) != 0) + { + JERRY_CONTEXT (ecma_gc_mark_recursion_limit)--; + /* Set the reference count of gray object to 0 */ + object_p->type_flags_refs &= (ecma_object_descriptor_t) (ECMA_OBJECT_REF_ONE - 1); + ecma_gc_mark (object_p); + JERRY_CONTEXT (ecma_gc_mark_recursion_limit)++; + } + else + { + /* Set the reference count of the non-marked gray object to 1 */ + object_p->type_flags_refs &= (ecma_object_descriptor_t) ((ECMA_OBJECT_REF_ONE << 1) - 1); + JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE); + } +#else /* (JERRY_GC_MARK_LIMIT == 0) */ + /* Set the reference count of gray object to 0 */ + object_p->type_flags_refs &= (ecma_object_descriptor_t) (ECMA_OBJECT_REF_ONE - 1); +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + } +} /* ecma_gc_set_object_visited */ + +/** + * Initialize GC information for the object + */ +void +ecma_init_gc_info (ecma_object_t *object_p) /**< object */ +{ + JERRY_CONTEXT (ecma_gc_objects_number)++; + JERRY_CONTEXT (ecma_gc_new_objects)++; + + JERRY_ASSERT (object_p->type_flags_refs < ECMA_OBJECT_REF_ONE); + object_p->type_flags_refs |= ECMA_OBJECT_REF_ONE; + + object_p->gc_next_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_gc_objects_cp), object_p); +} /* ecma_init_gc_info */ + +/** + * Increase reference counter of an object + * + * @return void + */ +void +ecma_ref_object_inline (ecma_object_t *object_p) /**< object */ +{ + if (JERRY_LIKELY (object_p->type_flags_refs < ECMA_OBJECT_MAX_REF)) + { + object_p->type_flags_refs = (ecma_object_descriptor_t) (object_p->type_flags_refs + ECMA_OBJECT_REF_ONE); + } + else + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } +} /* ecma_ref_object_inline */ + +/** + * Increase reference counter of an object + */ +void +ecma_ref_object (ecma_object_t *object_p) /**< object */ +{ + ecma_ref_object_inline (object_p); +} /* ecma_ref_object */ + +/** + * Decrease reference counter of an object + * + * @return void + */ +void +ecma_deref_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE); + object_p->type_flags_refs = (ecma_object_descriptor_t) (object_p->type_flags_refs - ECMA_OBJECT_REF_ONE); +} /* ecma_deref_object */ + +/** + * Mark objects referenced by global object + */ +static void +ecma_gc_mark_global_object (ecma_global_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p->extended_object.u.built_in.routine_id == 0); + + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, global_object_p->global_env_cp)); + +#if JERRY_BUILTIN_REALMS + ecma_gc_set_object_visited (ecma_get_object_from_value (global_object_p->this_binding)); +#endif /* JERRY_BUILTIN_REALMS */ + + if (global_object_p->global_scope_cp != global_object_p->global_env_cp) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, global_object_p->global_scope_cp)); + } + + jmem_cpointer_t *builtin_objects_p = global_object_p->builtin_objects; + + for (int i = 0; i < ECMA_BUILTIN_OBJECTS_COUNT; i++) + { + if (builtin_objects_p[i] != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_objects_p[i])); + } + } +} /* ecma_gc_mark_global_object */ + +/** + * Mark objects referenced by arguments object + */ +static void +ecma_gc_mark_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */ +{ + JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_CLASS); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (arguments_p->callee)); + + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env)); + } + + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + + for (uint32_t i = 0; i < arguments_number; i++) + { + if (ecma_is_value_object (argv_p[i])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (argv_p[i])); + } + } +} /* ecma_gc_mark_arguments_object */ + +/** + * Mark referenced object from property + */ +static void +ecma_gc_mark_properties (ecma_object_t *object_p, /**< object */ + bool mark_references) /**< mark references */ +{ + JERRY_UNUSED (mark_references); + +#if !JERRY_MODULE_SYSTEM + JERRY_ASSERT (!mark_references); +#endif /* !JERRY_MODULE_SYSTEM */ + + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (uint32_t index = 0; index < ECMA_PROPERTY_PAIR_ITEM_COUNT; index++) + { + uint8_t property = property_pair_p->header.types[index]; + + if (JERRY_LIKELY (ECMA_PROPERTY_IS_RAW (property))) + { + if (property & ECMA_PROPERTY_FLAG_DATA) + { + ecma_value_t value = property_pair_p->values[index].value; + + if (ecma_is_value_object (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (value)); + } + continue; + } + +#if JERRY_MODULE_SYSTEM + if (mark_references) + { + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + + ecma_property_value_t *accessor_objs_p = property_pair_p->values + index; + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p); + + if (get_set_pair_p->getter_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp)); + } + + if (get_set_pair_p->setter_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp)); + } + + continue; + } + + if (!ECMA_PROPERTY_IS_INTERNAL (property)) + { + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_DELETED || property == ECMA_PROPERTY_TYPE_HASHMAP); + continue; + } + + JERRY_ASSERT (property_pair_p->names_cp[index] >= LIT_INTERNAL_MAGIC_STRING_FIRST_DATA + && property_pair_p->names_cp[index] < LIT_MAGIC_STRING__COUNT); + + switch (property_pair_p->names_cp[index]) + { + case LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD: + { + ecma_environment_record_t *environment_record_p; + environment_record_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t, property_pair_p->values[index].value); + + if (environment_record_p->this_binding != ECMA_VALUE_UNINITIALIZED) + { + JERRY_ASSERT (ecma_is_value_object (environment_record_p->this_binding)); + ecma_gc_set_object_visited (ecma_get_object_from_value (environment_record_p->this_binding)); + } + + JERRY_ASSERT (ecma_is_value_object (environment_record_p->function_object)); + ecma_gc_set_object_visited (ecma_get_object_from_value (environment_record_p->function_object)); + break; + } + case LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS: + { + ecma_value_t *compact_collection_p; + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, property_pair_p->values[index].value); + + ecma_value_t *end_p = ecma_compact_collection_end (compact_collection_p); + ecma_value_t *current_p = compact_collection_p + 1; + + while (end_p - current_p >= ECMA_PRIVATE_ELEMENT_LIST_SIZE) + { + current_p++; /* skip the type */ + current_p++; /* skip the name */ + ecma_value_t value = *current_p++; + + if (!ecma_is_value_undefined (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (value)); + } + } + break; + } +#if JERRY_BUILTIN_CONTAINER + case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS: + { + ecma_value_t key_arg = ecma_make_object_value (object_p); + ecma_collection_t *refs_p; + + refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, property_pair_p->values[index].value); + + for (uint32_t j = 0; j < refs_p->item_count; j++) + { + const ecma_value_t reference_value = refs_p->buffer_p[j]; + + if (ecma_is_value_empty (reference_value)) + { + continue; + } + + ecma_object_t *reference_object_p = ecma_get_object_from_value (reference_value); + + JERRY_ASSERT (ecma_get_object_type (reference_object_p) == ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) reference_object_p; + + if (map_object_p->u.cls.type != ECMA_OBJECT_CLASS_CONTAINER + || map_object_p->u.cls.u2.container_id != LIT_MAGIC_STRING_WEAKMAP_UL + || !ecma_gc_is_object_visited (reference_object_p)) + { + continue; + } + + ecma_value_t value = ecma_op_container_find_weak_value (reference_object_p, key_arg); + + if (ecma_is_value_object (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (value)); + } + } + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + case LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES: + { + jerry_value_t value = property_pair_p->values[index].value; + + if (value == JMEM_CP_NULL) + { + JERRY_ASSERT (!(property & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)); + break; + } + + ecma_native_pointer_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value); + + do + { + jerry_object_native_info_t *native_info_p = item_p->native_info_p; + + JERRY_ASSERT (native_info_p != NULL && native_info_p->number_of_references > 0); + + uint8_t *start_p = ((uint8_t *) item_p->native_p) + native_info_p->offset_of_references; + ecma_value_t *value_p = (ecma_value_t *) start_p; + ecma_value_t *end_p = value_p + native_info_p->number_of_references; + + do + { + if (ecma_is_value_object (*value_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*value_p)); + } + } while (++value_p < end_p); + + if (property & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL) + { + break; + } + + item_p = &(((ecma_native_pointer_chain_t *) item_p)->next_p->data); + } while (item_p != NULL); + + break; + } + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +} /* ecma_gc_mark_properties */ + +/** + * Mark compiled code. + */ +static void +ecma_gc_mark_compiled_code (ecma_value_t script_value) /**< script value */ +{ + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (script_p->refs_and_type & CBC_SCRIPT_USER_VALUE_IS_OBJECT) + { + ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); + + JERRY_ASSERT (ecma_is_value_object (user_value)); + ecma_gc_set_object_visited (ecma_get_object_from_value (user_value)); + } + +#if JERRY_MODULE_SYSTEM + if (script_p->refs_and_type & CBC_SCRIPT_HAS_IMPORT_META) + { + ecma_value_t import_meta = CBC_SCRIPT_GET_IMPORT_META (script_p, script_p->refs_and_type); + + JERRY_ASSERT (ecma_is_value_object (import_meta)); + ecma_gc_set_object_visited (ecma_get_object_from_value (import_meta)); + } +#endif /* JERRY_MODULE_SYSTEM */ + +#if JERRY_BUILTIN_REALMS + ecma_gc_set_object_visited (script_p->realm_p); +#endif /* JERRY_BUILTIN_REALMS */ +} /* ecma_gc_mark_compiled_code */ + +/** + * Mark objects referenced by bound function object. + * + * @return void + */ +static void JERRY_ATTR_NOINLINE +ecma_gc_mark_bound_function_object (ecma_object_t *object_p) /**< bound function object */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + ecma_object_t *target_func_p; + target_func_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + ecma_gc_set_object_visited (target_func_p); + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + + if (!ecma_is_value_integer_number (args_len_or_this)) + { + if (ecma_is_value_object (args_len_or_this)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (args_len_or_this)); + } + + return; + } + + ecma_integer_value_t args_length = ecma_get_integer_from_value (args_len_or_this); + ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); + + JERRY_ASSERT (args_length > 0); + + for (ecma_integer_value_t i = 0; i < args_length; i++) + { + if (ecma_is_value_object (args_p[i])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (args_p[i])); + } + } +} /* ecma_gc_mark_bound_function_object */ + +/** + * Mark objects referenced by Promise built-in. + */ +static void +ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended object */ +{ + /* Mark promise result. */ + ecma_value_t result = ext_object_p->u.cls.u3.value; + + if (ecma_is_value_object (result)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (result)); + } + + /* Mark all reactions. */ + ecma_promise_object_t *promise_object_p = (ecma_promise_object_t *) ext_object_p; + + ecma_collection_t *collection_p = promise_object_p->reactions; + + if (collection_p != NULL) + { + ecma_value_t *buffer_p = collection_p->buffer_p; + ecma_value_t *buffer_end_p = buffer_p + collection_p->item_count; + + while (buffer_p < buffer_end_p) + { + ecma_value_t value = *buffer_p++; + + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, value)); + + if (JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*buffer_p++)); + } + + if (JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*buffer_p++)); + } + } + } +} /* ecma_gc_mark_promise_object */ + +#if JERRY_BUILTIN_CONTAINER +/** + * Mark objects referenced by Map built-in. + */ +static void +ecma_gc_mark_map_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + if (ecma_is_value_object (entry_p->key)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (entry_p->key)); + } + + if (ecma_is_value_object (entry_p->value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (entry_p->value)); + } + } +} /* ecma_gc_mark_map_object */ + +/** + * Mark objects referenced by WeakMap built-in. + */ +static void +ecma_gc_mark_weakmap_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + JERRY_ASSERT (ecma_is_value_object (entry_p->key)); + + if (ecma_is_value_object (entry_p->value) && ecma_gc_is_object_visited (ecma_get_object_from_value (entry_p->key))) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (entry_p->value)); + } + } +} /* ecma_gc_mark_weakmap_object */ + +/** + * Mark objects referenced by Set built-in. + */ +static void +ecma_gc_mark_set_object (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + if (ecma_is_value_object (*entry_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*entry_p)); + } + } +} /* ecma_gc_mark_set_object */ +#endif /* JERRY_BUILTIN_CONTAINER */ + +/** + * Mark objects referenced by inactive generator functions, async functions, etc. + */ +static void +ecma_gc_mark_executable_object (ecma_object_t *object_p) /**< object */ +{ + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_ASYNC_GENERATOR_CALLED) + { + ecma_value_t task = executable_object_p->extended_object.u.cls.u3.head; + + while (!ECMA_IS_INTERNAL_VALUE_NULL (task)) + { + ecma_async_generator_task_t *task_p; + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, task); + + JERRY_ASSERT (ecma_is_value_object (task_p->promise)); + ecma_gc_set_object_visited (ecma_get_object_from_value (task_p->promise)); + + if (ecma_is_value_object (task_p->operation_value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (task_p->operation_value)); + } + + task = task_p->next; + } + } + + ecma_gc_set_object_visited (executable_object_p->frame_ctx.lex_env_p); + ecma_gc_set_object_visited (executable_object_p->shared.function_object_p); + + if (!ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p) + && !(executable_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD)) + { + /* All objects referenced by running executable objects are strong roots, + * and a finished executable object cannot refer to other values. */ + return; + } + + if (ecma_is_value_object (executable_object_p->frame_ctx.this_binding)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (executable_object_p->frame_ctx.this_binding)); + } + + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; + size_t register_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + register_end = args_p->register_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + register_end = args_p->register_end; + } + + ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + ecma_value_t *register_end_p = register_p + register_end; + + while (register_p < register_end_p) + { + if (ecma_is_value_object (*register_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p)); + } + + register_p++; + } + + if (executable_object_p->frame_ctx.context_depth > 0) + { + ecma_value_t *context_end_p = register_p; + + register_p += executable_object_p->frame_ctx.context_depth; + + ecma_value_t *context_top_p = register_p; + + do + { + if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1]))) + { + ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]); + JERRY_ASSERT (last_item_p >= context_end_p); + context_top_p--; + + do + { + --context_top_p; + if (ecma_is_value_object (*context_top_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*context_top_p)); + } + } while (context_top_p > last_item_p); + + continue; + } + + uint32_t offsets = vm_get_context_value_offsets (context_top_p); + + while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) + { + int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets); + + if (ecma_is_value_object (context_top_p[offset])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (context_top_p[offset])); + } + + offsets >>= VM_CONTEXT_OFFSET_SHIFT; + } + + JERRY_ASSERT (context_top_p >= context_end_p + offsets); + context_top_p -= offsets; + } while (context_top_p > context_end_p); + } + + register_end_p = executable_object_p->frame_ctx.stack_top_p; + + while (register_p < register_end_p) + { + if (ecma_is_value_object (*register_p)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p)); + } + + register_p++; + } + + if (ecma_is_value_object (executable_object_p->iterator)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (executable_object_p->iterator)); + } +} /* ecma_gc_mark_executable_object */ + +#if JERRY_BUILTIN_PROXY +/** + * Mark the objects referenced by a proxy object + */ +static void +ecma_gc_mark_proxy_object (ecma_object_t *object_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (object_p)); + + ecma_proxy_object_t *proxy_p = (ecma_proxy_object_t *) object_p; + + if (!ecma_is_value_null (proxy_p->target)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (proxy_p->target)); + } + + if (!ecma_is_value_null (proxy_p->handler)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (proxy_p->handler)); + } +} /* ecma_gc_mark_proxy_object */ +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * Mark objects as visited starting from specified object as root + */ +static void +ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (ecma_gc_is_object_visited (object_p)); + + if (ecma_is_lexical_environment (object_p)) + { + jmem_cpointer_t outer_lex_env_cp = object_p->u2.outer_reference_cp; + + if (outer_lex_env_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, outer_lex_env_cp)); + } + + switch (ecma_get_lex_env_type (object_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { +#if JERRY_MODULE_SYSTEM + if (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) + { + if (ECMA_LEX_ENV_CLASS_IS_MODULE (object_p)) + { + ecma_gc_mark_properties (object_p, true); + } + + ecma_gc_set_object_visited (((ecma_lexical_environment_class_t *) object_p)->object_p); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND: + { + ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p); + ecma_gc_set_object_visited (binding_object_p); + return; + } + default: + { + break; + } + } + } + else + { + /** + * Have the object's prototype here so the object could set it to JMEM_CP_NULL + * if the prototype should be ignored (like in case of PROXY). + */ + jmem_cpointer_t proto_cp = object_p->u2.prototype_cp; + + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + { + ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) object_p; + + if (extended_object_p->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL) + { + ecma_gc_mark_global_object ((ecma_global_object_t *) object_p); + } + +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = extended_object_p->u.built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = ((ecma_extended_built_in_object_t *) object_p)->built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + ecma_gc_mark_arguments_object (ext_object_p); + break; + } +#if JERRY_PARSER + case ECMA_OBJECT_CLASS_SCRIPT: + { + const ecma_compiled_code_t *compiled_code_p; + compiled_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); + break; + } +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + ecma_gc_set_object_visited (ecma_typedarray_get_arraybuffer (object_p)); + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + JERRY_ASSERT (proto_cp == JMEM_CP_NULL); + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ext_object_p->u.cls.u3.value)); + ecma_gc_mark_properties (object_p, true); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE: + { + ecma_module_t *module_p = ((ecma_module_t *) ext_object_p); + + if (module_p->scope_p != NULL) + { + ecma_gc_set_object_visited (((ecma_module_t *) ext_object_p)->scope_p); + } + + if (module_p->namespace_object_p != NULL) + { + ecma_gc_set_object_visited (((ecma_module_t *) ext_object_p)->namespace_object_p); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) + && module_p->u.compiled_code_p != NULL) + { + const ecma_compiled_code_t *compiled_code_p = module_p->u.compiled_code_p; + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); + } + + ecma_module_node_t *node_p = module_p->imports_p; + + while (node_p != NULL) + { + if (ecma_is_value_object (node_p->u.path_or_module)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (node_p->u.path_or_module)); + } + + node_p = node_p->next_p; + } + break; + } +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_DATAVIEW + case ECMA_OBJECT_CLASS_DATAVIEW: + { + ecma_dataview_object_t *dataview_p = (ecma_dataview_object_t *) object_p; + ecma_gc_set_object_visited (dataview_p->buffer_p); + break; + } +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_CONTAINER: + { + if (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_gc_mark_map_object (object_p); + break; + } + if (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL) + { + ecma_gc_mark_weakmap_object (object_p); + break; + } + if (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_SET_UL) + { + ecma_gc_mark_set_object (object_p); + break; + } + JERRY_ASSERT (ext_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKSET_UL); + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + case ECMA_OBJECT_CLASS_GENERATOR: + case ECMA_OBJECT_CLASS_ASYNC_GENERATOR: + { + ecma_gc_mark_executable_object (object_p); + break; + } + case ECMA_OBJECT_CLASS_PROMISE: + { + ecma_gc_mark_promise_object (ext_object_p); + break; + } + case ECMA_OBJECT_CLASS_PROMISE_CAPABILITY: + { + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) object_p; + + if (ecma_is_value_object (capability_p->header.u.cls.u3.promise)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->header.u.cls.u3.promise)); + } + if (ecma_is_value_object (capability_p->resolve)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->resolve)); + } + if (ecma_is_value_object (capability_p->reject)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->reject)); + } + break; + } + case ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR: + { + ecma_async_from_sync_iterator_object_t *iter_p = (ecma_async_from_sync_iterator_object_t *) ext_object_p; + + ecma_gc_set_object_visited (ecma_get_object_from_value (iter_p->header.u.cls.u3.sync_iterator)); + + if (!ecma_is_value_undefined (iter_p->sync_next_method)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (iter_p->sync_next_method)); + } + + break; + } + case ECMA_OBJECT_CLASS_ARRAY_ITERATOR: + case ECMA_OBJECT_CLASS_SET_ITERATOR: + case ECMA_OBJECT_CLASS_MAP_ITERATOR: + { + ecma_value_t iterated_value = ext_object_p->u.cls.u3.iterated_value; + if (!ecma_is_value_empty (iterated_value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (iterated_value)); + } + break; + } +#if JERRY_BUILTIN_REGEXP + case ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR: + { + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) object_p; + ecma_value_t regexp = regexp_string_iterator_obj->iterating_regexp; + ecma_gc_set_object_visited (ecma_get_object_from_value (regexp)); + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ + default: + { + /* The ECMA_OBJECT_CLASS__MAX type represents an uninitialized class. */ + JERRY_ASSERT (ext_object_p->u.cls.type <= ECMA_OBJECT_CLASS__MAX); + break; + } + } + + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = ((ecma_extended_built_in_object_t *) object_p)->built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (ext_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL)) + { + /* Template objects are never marked. */ + JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE); + return; + } + + if (ecma_op_array_is_fast_array (ext_object_p)) + { + if (object_p->u1.property_list_cp != JMEM_CP_NULL) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < ext_object_p->u.array.length; i++) + { + if (ecma_is_value_object (values_p[i])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (values_p[i])); + } + } + } + + if (proto_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); + } + return; + } + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + ecma_gc_mark_proxy_object (object_p); + /* Prototype of proxy object is a bit set. */ + proto_cp = JMEM_CP_NULL; + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_FUNCTION: + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + ecma_gc_set_object_visited ( + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp)); + + const ecma_compiled_code_t *compiled_code_p = ecma_op_function_get_compiled_code (ext_func_p); + + if (CBC_FUNCTION_IS_ARROW (compiled_code_p->status_flags)) + { + ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p; + + if (ecma_is_value_object (arrow_func_p->this_binding)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (arrow_func_p->this_binding)); + } + + if (ecma_is_value_object (arrow_func_p->new_target)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (arrow_func_p->new_target)); + } + } + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + /* Static snapshot functions have a global realm */ + break; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_gc_mark_bound_function_object (object_p); + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value = ext_func_p->u.built_in.realm_value; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value)); +#endif /* JERRY_BUILTIN_REALMS */ + + if (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER) + { + switch (ext_func_p->u.built_in.routine_id) + { + case ECMA_NATIVE_HANDLER_PROMISE_RESOLVE: + case ECMA_NATIVE_HANDLER_PROMISE_REJECT: + { + ecma_promise_resolver_t *resolver_obj_p = (ecma_promise_resolver_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (resolver_obj_p->promise)); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY: + case ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY: + { + ecma_promise_finally_function_t *finally_obj_p = (ecma_promise_finally_function_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (finally_obj_p->constructor)); + ecma_gc_set_object_visited (ecma_get_object_from_value (finally_obj_p->on_finally)); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR: + { + ecma_promise_capability_executor_t *executor_p = (ecma_promise_capability_executor_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->capability)); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER: + { + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->capability)); + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->values)); + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->remaining_elements)); + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_NATIVE_HANDLER_PROXY_REVOKE: + { + ecma_revocable_proxy_object_t *rev_proxy_p = (ecma_revocable_proxy_object_t *) object_p; + + if (!ecma_is_value_null (rev_proxy_p->proxy)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (rev_proxy_p->proxy)); + } + + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_NATIVE_HANDLER_VALUE_THUNK: + case ECMA_NATIVE_HANDLER_VALUE_THROWER: + { + ecma_promise_value_thunk_t *thunk_obj_p = (ecma_promise_value_thunk_t *) object_p; + + if (ecma_is_value_object (thunk_obj_p->value)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (thunk_obj_p->value)); + } + break; + } + case ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP: + { + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + } + break; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_gc_mark_compiled_code (((ecma_extended_object_t *) object_p)->u.constructor_function.script_value); + break; + } +#if JERRY_BUILTIN_REALMS + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, native_function_p->realm_value)); + break; + } +#endif /* JERRY_BUILTIN_REALMS */ + default: + { + break; + } + } + + if (proto_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); + } + } + + ecma_gc_mark_properties (object_p, false); +} /* ecma_gc_mark */ + +/** + * Free the native handle/pointer by calling its free callback. + */ +static void +ecma_gc_free_native_pointer (ecma_property_t property, /**< property descriptor */ + ecma_value_t value) /**< property value */ +{ + if (JERRY_LIKELY (property & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + JERRY_ASSERT (value != JMEM_CP_NULL); + + ecma_native_pointer_t *native_pointer_p; + native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value); + + if (native_pointer_p->native_info_p != NULL) + { + jerry_object_native_free_cb_t free_cb = native_pointer_p->native_info_p->free_cb; + + if (free_cb != NULL) + { + free_cb (native_pointer_p->native_p, native_pointer_p->native_info_p); + } + } + + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + return; + } + + if (value == JMEM_CP_NULL) + { + return; + } + + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value); + + do + { + if (item_p->data.native_info_p != NULL) + { + jerry_object_native_free_cb_t free_cb = item_p->data.native_info_p->free_cb; + + if (free_cb != NULL) + { + free_cb (item_p->data.native_p, item_p->data.native_info_p); + } + } + + ecma_native_pointer_chain_t *next_p = item_p->next_p; + + jmem_heap_free_block (item_p, sizeof (ecma_native_pointer_chain_t)); + + item_p = next_p; + } while (item_p != NULL); +} /* ecma_gc_free_native_pointer */ + +/** + * Free specified arguments object. + * + * @return allocated object's size + */ +static size_t +ecma_free_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */ +{ + JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_CLASS); + + size_t object_size = sizeof (ecma_unmapped_arguments_t); + + if (ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + object_size = sizeof (ecma_mapped_arguments_t); + +#if JERRY_SNAPSHOT_EXEC + if (!(mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE)) +#endif /* JERRY_SNAPSHOT_EXEC */ + { + ecma_compiled_code_t *byte_code_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code); + + ecma_bytecode_deref (byte_code_p); + } + } + + ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) ext_object_p) + object_size); + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p; + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + + for (uint32_t i = 0; i < arguments_number; i++) + { + ecma_free_value_if_not_object (argv_p[i]); + } + + uint32_t saved_argument_count = JERRY_MAX (arguments_number, arguments_p->header.u.cls.u2.formal_params_number); + + return object_size + (saved_argument_count * sizeof (ecma_value_t)); +} /* ecma_free_arguments_object */ + +/** + * Free specified fast access mode array object. + */ +static void +ecma_free_fast_access_array (ecma_object_t *object_p) /**< fast access mode array object to free */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (ext_object_p->u.array.length); + + if (object_p->u1.property_list_cp != JMEM_CP_NULL) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < aligned_length; i++) + { + ecma_free_value_if_not_object (values_p[i]); + } + + jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t)); + } + + ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t)); +} /* ecma_free_fast_access_array */ + +/** + * Free non-objects referenced by inactive generator functions, async functions, etc. + * + * @return total object size + */ +static size_t +ecma_gc_free_executable_object (ecma_object_t *object_p) /**< object */ +{ + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; + size_t size, register_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + + size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t)); + ecma_bytecode_deref ((ecma_compiled_code_t *) bytecode_header_p); + + uint16_t executable_obj_flags = executable_object_p->extended_object.u.cls.u2.executable_obj_flags; + + JERRY_ASSERT (!(executable_obj_flags & ECMA_EXECUTABLE_OBJECT_RUNNING)); + + if (executable_obj_flags & ECMA_ASYNC_GENERATOR_CALLED) + { + ecma_value_t task = executable_object_p->extended_object.u.cls.u3.head; + + while (!ECMA_IS_INTERNAL_VALUE_NULL (task)) + { + ecma_async_generator_task_t *task_p; + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, task); + + JERRY_ASSERT (ecma_is_value_object (task_p->promise)); + ecma_free_value_if_not_object (task_p->operation_value); + + task = task_p->next; + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + } + } + + if (executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + return size; + } + + ecma_free_value_if_not_object (executable_object_p->frame_ctx.this_binding); + + ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + ecma_value_t *register_end_p = register_p + register_end; + + while (register_p < register_end_p) + { + ecma_free_value_if_not_object (*register_p++); + } + + if (executable_object_p->frame_ctx.context_depth > 0) + { + ecma_value_t *context_end_p = register_p; + + register_p += executable_object_p->frame_ctx.context_depth; + + ecma_value_t *context_top_p = register_p; + + do + { + context_top_p[-1] &= (uint32_t) ~VM_CONTEXT_HAS_LEX_ENV; + + if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1]))) + { + ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]); + JERRY_ASSERT (last_item_p >= context_end_p); + context_top_p--; + + do + { + ecma_free_value_if_not_object (*(--context_top_p)); + } while (context_top_p > last_item_p); + + continue; + } + + uint32_t offsets = vm_get_context_value_offsets (context_top_p); + + while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) + { + int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets); + + if (ecma_is_value_object (context_top_p[offset])) + { + context_top_p[offset] = ECMA_VALUE_UNDEFINED; + } + + offsets >>= VM_CONTEXT_OFFSET_SHIFT; + } + + context_top_p = vm_stack_context_abort (&executable_object_p->frame_ctx, context_top_p); + } while (context_top_p > context_end_p); + } + + register_end_p = executable_object_p->frame_ctx.stack_top_p; + + while (register_p < register_end_p) + { + ecma_free_value_if_not_object (*register_p++); + } + + return size; +} /* ecma_gc_free_executable_object */ + +JERRY_STATIC_ASSERT (!ECMA_PROPERTY_IS_RAW (ECMA_PROPERTY_TYPE_DELETED), + ecma_property_type_deleted_must_not_be_raw_property); +JERRY_STATIC_ASSERT ((((int)ECMA_PROPERTY_TYPE_DELETED & (int)ECMA_PROPERTY_FLAG_LCACHED) == 0), + ecma_property_type_deleted_must_not_have_lcached_flag); +JERRY_STATIC_ASSERT ((((int)ECMA_GC_FREE_SECOND_PROPERTY) == 1), ecma_gc_free_second_must_be_one); + +/** + * Free property of an object + */ +void +ecma_gc_free_property (ecma_object_t *object_p, /**< object */ + ecma_property_pair_t *prop_pair_p, /**< property pair */ + uint32_t options) /**< option bits including property index */ +{ + /* Both cannot be deleted. */ + JERRY_ASSERT (prop_pair_p->header.types[0] != ECMA_PROPERTY_TYPE_DELETED + || prop_pair_p->header.types[1] != ECMA_PROPERTY_TYPE_DELETED); + JERRY_ASSERT (prop_pair_p->header.types[0] != ECMA_PROPERTY_TYPE_HASHMAP); + + uint32_t index = (options & ECMA_GC_FREE_SECOND_PROPERTY); + jmem_cpointer_t name_cp = prop_pair_p->names_cp[index]; + ecma_property_t *property_p = prop_pair_p->header.types + index; + ecma_property_t property = *property_p; + +#if JERRY_LCACHE + if ((property & ECMA_PROPERTY_FLAG_LCACHED) != 0) + { + ecma_lcache_invalidate (object_p, name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + + if (ECMA_PROPERTY_IS_RAW (property)) + { + if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_PTR) + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp); + ecma_deref_ecma_string (prop_name_p); + } + + if (property & ECMA_PROPERTY_FLAG_DATA) + { + ecma_free_value_if_not_object (prop_pair_p->values[index].value); + return; + } + + if (JERRY_UNLIKELY (options & ECMA_GC_FREE_REFERENCES)) + { + return; + } + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_pair_p->values[index].getter_setter_pair_cp); + jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + return; + } + + if (property == ECMA_PROPERTY_TYPE_DELETED) + { + return; + } + + ecma_value_t value = prop_pair_p->values[index].value; + + switch (name_cp) + { + case LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD: + { + ecma_environment_record_t *environment_record_p; + environment_record_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t, value); + jmem_heap_free_block (environment_record_p, sizeof (ecma_environment_record_t)); + break; + } + case LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED: + { + ecma_value_t *compact_collection_p; + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + ecma_compact_collection_free (compact_collection_p); + break; + } + case LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS: + { + ecma_value_t *compact_collection_p; + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + + ecma_value_t *end_p = ecma_compact_collection_end (compact_collection_p); + ecma_value_t *current_p = compact_collection_p + 1; + + JERRY_ASSERT ((end_p - current_p) % ECMA_PRIVATE_ELEMENT_LIST_SIZE == 0); + + while (current_p < end_p) + { + current_p++; /* skip the type */ + ecma_deref_ecma_string (ecma_get_prop_name_from_value (*current_p++)); + current_p++; /* skip the value */ + } + + ecma_compact_collection_destroy (compact_collection_p); + break; + } +#if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER + case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS: + { + ecma_collection_t *refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, value); + for (uint32_t j = 0; j < refs_p->item_count; j++) + { + const ecma_value_t reference_value = refs_p->buffer_p[j]; + + if (!ecma_is_value_empty (reference_value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (reference_value); + + if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_WEAKREF)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ext_obj_p->u.cls.u3.target = ECMA_VALUE_UNDEFINED; + continue; + } + ecma_op_container_remove_weak_entry (obj_p, ecma_make_object_value (object_p)); + } + } + + ecma_collection_destroy (refs_p); + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + default: + { + JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER + || name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + ecma_gc_free_native_pointer (property, value); + break; + } + } +} /* ecma_gc_free_property */ + +/** + * Free properties of an object + */ +void +ecma_gc_free_properties (ecma_object_t *object_p, /**< object */ + uint32_t options) /**< option bits */ +{ + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + prop_iter_cp = object_p->u1.property_list_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_gc_free_property (object_p, prop_pair_p, i | options); + } + + prop_iter_cp = prop_iter_p->next_property_cp; + + ecma_dealloc_property_pair (prop_pair_p); + } +} /* ecma_gc_free_properties */ + +/** + * Free specified object. + */ +static void +ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_gc_is_object_visited (object_p)); + + JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_objects_number) > 0); + JERRY_CONTEXT (ecma_gc_objects_number)--; + + if (ecma_is_lexical_environment (object_p)) + { +#if JERRY_MODULE_SYSTEM + if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)) + { + if (ECMA_LEX_ENV_CLASS_IS_MODULE (object_p)) + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES); + } + + ecma_dealloc_extended_object (object_p, sizeof (ecma_lexical_environment_class_t)); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS); + } + + ecma_dealloc_object (object_p); + return; + } + + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + size_t ext_object_size = sizeof (ecma_extended_object_t); + + switch (object_type) + { + case ECMA_OBJECT_TYPE_GENERAL: + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS); + ecma_dealloc_object (object_p); + return; + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + { + if (((ecma_extended_object_t *) object_p)->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL) + { + ext_object_size = sizeof (ecma_global_object_t); + break; + } + + uint8_t bitset_size = ((ecma_extended_object_t *) object_p)->u.built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { + ext_object_size = sizeof (ecma_extended_built_in_object_t); + uint8_t bitset_size = ((ecma_extended_built_in_object_t *) object_p)->built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + case ECMA_OBJECT_CLASS_NUMBER: + case ECMA_OBJECT_CLASS_SYMBOL: +#if JERRY_BUILTIN_BIGINT + case ECMA_OBJECT_CLASS_BIGINT: +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_free_value (ext_object_p->u.cls.u3.value); + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + ext_object_size = ecma_free_arguments_object (ext_object_p); + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ext_object_p->u.cls.u2.typedarray_flags & ECMA_TYPEDARRAY_IS_EXTENDED) + { + ext_object_size = sizeof (ecma_extended_typedarray_object_t); + } + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES); + ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t)); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER + case ECMA_OBJECT_CLASS_SCRIPT: + { + ecma_compiled_code_t *compiled_code_p; + compiled_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + ecma_bytecode_deref (compiled_code_p); + break; + } +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + case ECMA_OBJECT_CLASS_DATE: + { + ext_object_size = sizeof (ecma_date_object_t); + break; + } +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + case ECMA_OBJECT_CLASS_REGEXP: + { + ecma_compiled_code_t *bytecode_p = + ECMA_GET_INTERNAL_VALUE_ANY_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + + ecma_bytecode_deref (bytecode_p); + + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ + case ECMA_OBJECT_CLASS_STRING_ITERATOR: + { + ecma_value_t iterated_value = ext_object_p->u.cls.u3.iterated_value; + + if (!ecma_is_value_empty (iterated_value)) + { + ecma_deref_ecma_string (ecma_get_string_from_value (iterated_value)); + } + + break; + } +#if JERRY_BUILTIN_REGEXP + case ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR: + { + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) object_p; + ecma_value_t iterated_string = regexp_string_iterator_obj->iterated_string; + + if (!ecma_is_value_empty (iterated_string)) + { + ecma_deref_ecma_string (ecma_get_string_from_value (iterated_string)); + } + + ext_object_size = sizeof (ecma_regexp_string_iterator_t); + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_ARRAY_BUFFER: +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + case ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER: +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + { + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (ext_object_p) & ECMA_ARRAYBUFFER_HAS_POINTER)) + { + ext_object_size += ext_object_p->u.cls.u3.length; + break; + } + + ext_object_size = sizeof (ecma_arraybuffer_pointer_t); + + if (ECMA_ARRAYBUFFER_GET_FLAGS (ext_object_p) & ECMA_ARRAYBUFFER_ALLOCATED) + { + ecma_arraybuffer_release_buffer (object_p); + } + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_WEAKREF + case ECMA_OBJECT_CLASS_WEAKREF: + { + ecma_value_t target = ext_object_p->u.cls.u3.target; + + if (!ecma_is_value_undefined (target)) + { + ecma_op_object_unref_weak (ecma_get_object_from_value (target), ecma_make_object_value (object_p)); + } + break; + } +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_CONTAINER: + { + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + ecma_op_container_free_entries (object_p); + ecma_collection_destroy (container_p); + break; + } +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_DATAVIEW + case ECMA_OBJECT_CLASS_DATAVIEW: + { + ext_object_size = sizeof (ecma_dataview_object_t); + break; + } +#endif /* JERRY_BUILTIN_DATAVIEW */ + case ECMA_OBJECT_CLASS_GENERATOR: + case ECMA_OBJECT_CLASS_ASYNC_GENERATOR: + { + ext_object_size = ecma_gc_free_executable_object (object_p); + break; + } + case ECMA_OBJECT_CLASS_PROMISE: + { + ecma_free_value_if_not_object (ext_object_p->u.cls.u3.value); + + /* Reactions only contains objects. */ + ecma_collection_destroy (((ecma_promise_object_t *) object_p)->reactions); + + ext_object_size = sizeof (ecma_promise_object_t); + break; + } + case ECMA_OBJECT_CLASS_PROMISE_CAPABILITY: + { + ext_object_size = sizeof (ecma_promise_capabality_t); + break; + } + case ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR: + { + ext_object_size = sizeof (ecma_async_from_sync_iterator_object_t); + break; + } +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE: + { + ecma_module_release_module ((ecma_module_t *) ext_object_p); + ext_object_size = sizeof (ecma_module_t); + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + /* The ECMA_OBJECT_CLASS__MAX type represents an uninitialized class. */ + JERRY_ASSERT (ext_object_p->u.cls.type <= ECMA_OBJECT_CLASS__MAX); + break; + } + } + + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ext_object_size = sizeof (ecma_extended_built_in_object_t); + uint8_t bitset_size = ((ecma_extended_built_in_object_t *) object_p)->built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_ARRAY: + { + if (ecma_op_array_is_fast_array ((ecma_extended_object_t *) object_p)) + { + ecma_free_fast_access_array (object_p); + return; + } + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + ext_object_size = sizeof (ecma_proxy_object_t); + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_FUNCTION: + { + /* Function with byte-code (not a built-in function). */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + +#if JERRY_SNAPSHOT_EXEC + if (ext_func_p->u.function.bytecode_cp != ECMA_NULL_POINTER) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + ecma_compiled_code_t *byte_code_p = + (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_func_p->u.function.bytecode_cp)); + + if (CBC_FUNCTION_IS_ARROW (byte_code_p->status_flags)) + { + ecma_free_value_if_not_object (((ecma_arrow_function_t *) object_p)->this_binding); + ecma_free_value_if_not_object (((ecma_arrow_function_t *) object_p)->new_target); + ext_object_size = sizeof (ecma_arrow_function_t); + } + + ecma_bytecode_deref (byte_code_p); +#if JERRY_SNAPSHOT_EXEC + } + else + { + ext_object_size = sizeof (ecma_static_function_t); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + ecma_extended_object_t *extended_func_p = (ecma_extended_object_t *) object_p; + + if (!ecma_builtin_function_is_routine (object_p)) + { + uint8_t bitset_size = extended_func_p->u.built_in.u.length_and_bitset_size; + ext_object_size += sizeof (uint64_t) * (bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + break; + } + + if (extended_func_p->u.built_in.id != ECMA_BUILTIN_ID_HANDLER) + { + break; + } + + switch (extended_func_p->u.built_in.routine_id) + { + case ECMA_NATIVE_HANDLER_PROMISE_RESOLVE: + case ECMA_NATIVE_HANDLER_PROMISE_REJECT: + { + ext_object_size = sizeof (ecma_promise_resolver_t); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY: + case ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY: + { + ext_object_size = sizeof (ecma_promise_finally_function_t); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR: + { + ext_object_size = sizeof (ecma_promise_capability_executor_t); + break; + } + case ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER: + { + ext_object_size = sizeof (ecma_promise_all_executor_t); + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_NATIVE_HANDLER_PROXY_REVOKE: + { + ext_object_size = sizeof (ecma_revocable_proxy_object_t); + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_NATIVE_HANDLER_VALUE_THUNK: + case ECMA_NATIVE_HANDLER_VALUE_THROWER: + { + ecma_free_value_if_not_object (((ecma_promise_value_thunk_t *) object_p)->value); + ext_object_size = sizeof (ecma_promise_value_thunk_t); + break; + } + case ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP: + { + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ext_object_size = sizeof (ecma_bound_function_t); + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + + ecma_free_value (bound_func_p->target_length); + + if (!ecma_is_value_integer_number (args_len_or_this)) + { + ecma_free_value_if_not_object (args_len_or_this); + break; + } + + ecma_integer_value_t args_length = ecma_get_integer_from_value (args_len_or_this); + ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); + + for (ecma_integer_value_t i = 0; i < args_length; i++) + { + ecma_free_value_if_not_object (args_p[i]); + } + + size_t args_size = ((size_t) args_length) * sizeof (ecma_value_t); + ext_object_size += args_size; + break; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_script_deref (((ecma_extended_object_t *) object_p)->u.constructor_function.script_value); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ext_object_size = sizeof (ecma_native_function_t); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS); + ecma_dealloc_extended_object (object_p, ext_object_size); +} /* ecma_gc_free_object */ + +/** + * Run garbage collection, freeing objects that are no longer referenced. + */ +void +ecma_gc_run (void) +{ +#if (JERRY_GC_MARK_LIMIT != 0) + JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_mark_recursion_limit) == JERRY_GC_MARK_LIMIT); +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + + JERRY_CONTEXT (ecma_gc_new_objects) = 0; + + ecma_object_t black_list_head; + black_list_head.gc_next_cp = JMEM_CP_NULL; + ecma_object_t *black_end_p = &black_list_head; + + ecma_object_t white_gray_list_head; + white_gray_list_head.gc_next_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + ecma_object_t *obj_prev_p = &white_gray_list_head; + jmem_cpointer_t obj_iter_cp = obj_prev_p->gc_next_cp; + ecma_object_t *obj_iter_p; + + /* Move root objects (i.e. they have global or stack references) to the black list. */ + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + const jmem_cpointer_t obj_next_cp = obj_iter_p->gc_next_cp; + + JERRY_ASSERT (obj_prev_p == NULL + || ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_prev_p->gc_next_cp) == obj_iter_p); + + if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE) + { + /* Moving the object to list of marked objects. */ + obj_prev_p->gc_next_cp = obj_next_cp; + + black_end_p->gc_next_cp = obj_iter_cp; + black_end_p = obj_iter_p; + } + else + { + obj_iter_p->type_flags_refs |= ECMA_OBJECT_NON_VISITED; + obj_prev_p = obj_iter_p; + } + + obj_iter_cp = obj_next_cp; + } + + black_end_p->gc_next_cp = JMEM_CP_NULL; + + /* Mark root objects. */ + obj_iter_cp = black_list_head.gc_next_cp; + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + ecma_gc_mark (obj_iter_p); + obj_iter_cp = obj_iter_p->gc_next_cp; + } + + /* Mark non-root objects. */ + bool marked_anything_during_current_iteration; + + do + { +#if (JERRY_GC_MARK_LIMIT != 0) + JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_mark_recursion_limit) == JERRY_GC_MARK_LIMIT); +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + + marked_anything_during_current_iteration = false; + + obj_prev_p = &white_gray_list_head; + obj_iter_cp = obj_prev_p->gc_next_cp; + + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + const jmem_cpointer_t obj_next_cp = obj_iter_p->gc_next_cp; + + JERRY_ASSERT (obj_prev_p == NULL + || ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_prev_p->gc_next_cp) == obj_iter_p); + + if (ecma_gc_is_object_visited (obj_iter_p)) + { + /* Moving the object to list of marked objects */ + obj_prev_p->gc_next_cp = obj_next_cp; + + black_end_p->gc_next_cp = obj_iter_cp; + black_end_p = obj_iter_p; + +#if (JERRY_GC_MARK_LIMIT != 0) + if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE) + { + /* Set the reference count of non-marked gray object to 0 */ + obj_iter_p->type_flags_refs &= (ecma_object_descriptor_t) (ECMA_OBJECT_REF_ONE - 1); + ecma_gc_mark (obj_iter_p); + marked_anything_during_current_iteration = true; + } +#else /* (JERRY_GC_MARK_LIMIT == 0) */ + marked_anything_during_current_iteration = true; +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + } + else + { + obj_prev_p = obj_iter_p; + } + + obj_iter_cp = obj_next_cp; + } + } while (marked_anything_during_current_iteration); + + black_end_p->gc_next_cp = JMEM_CP_NULL; + JERRY_CONTEXT (ecma_gc_objects_cp) = black_list_head.gc_next_cp; + + /* Sweep objects that are currently unmarked. */ + obj_iter_cp = white_gray_list_head.gc_next_cp; + + while (obj_iter_cp != JMEM_CP_NULL) + { + obj_iter_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + const jmem_cpointer_t obj_next_cp = obj_iter_p->gc_next_cp; + + JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p)); + + ecma_gc_free_object (obj_iter_p); + obj_iter_cp = obj_next_cp; + } + +#if JERRY_BUILTIN_REGEXP + /* Free RegExp bytecodes stored in cache */ + re_cache_gc (); +#endif /* JERRY_BUILTIN_REGEXP */ +} /* ecma_gc_run */ + +/** + * Try to free some memory (depending on memory pressure). + * + * When called with JMEM_PRESSURE_FULL, the engine will be terminated with JERRY_FATAL_OUT_OF_MEMORY. + */ +void +ecma_free_unused_memory (jmem_pressure_t pressure) /**< current pressure */ +{ + if (JERRY_LIKELY (pressure == JMEM_PRESSURE_LOW)) + { +#if JERRY_PROPERTY_HASHMAP + if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) > ECMA_PROP_HASHMAP_ALLOC_ON) + { + --JERRY_CONTEXT (ecma_prop_hashmap_alloc_state); + } + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_HIGH_PRESSURE_GC; +#endif /* JERRY_PROPERTY_HASHMAP */ + /* + * If there is enough newly allocated objects since last GC, probably it is worthwhile to start GC now. + * Otherwise, probability to free sufficient space is considered to be low. + */ + size_t new_objects_fraction = CONFIG_ECMA_GC_NEW_OBJECTS_FRACTION; + + if (JERRY_CONTEXT (ecma_gc_new_objects) * new_objects_fraction > JERRY_CONTEXT (ecma_gc_objects_number)) + { + ecma_gc_run (); + } + + return; + } + else if (pressure == JMEM_PRESSURE_HIGH) + { + /* Freeing as much memory as we currently can */ +#if JERRY_PROPERTY_HASHMAP + if (JERRY_CONTEXT (status_flags) & ECMA_STATUS_HIGH_PRESSURE_GC) + { + JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) = ECMA_PROP_HASHMAP_ALLOC_MAX; + } + else if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) < ECMA_PROP_HASHMAP_ALLOC_MAX) + { + ++JERRY_CONTEXT (ecma_prop_hashmap_alloc_state); + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_HIGH_PRESSURE_GC; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + ecma_gc_run (); + +#if JERRY_PROPERTY_HASHMAP + /* Free hashmaps of remaining objects. */ + jmem_cpointer_t obj_iter_cp = JERRY_CONTEXT (ecma_gc_objects_cp); + + while (obj_iter_cp != JMEM_CP_NULL) + { + ecma_object_t *obj_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_iter_cp); + + if (!ecma_is_lexical_environment (obj_iter_p) + || ecma_get_lex_env_type (obj_iter_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + if (!ecma_is_lexical_environment (obj_iter_p) && ecma_op_object_is_fast_array (obj_iter_p)) + { + obj_iter_cp = obj_iter_p->gc_next_cp; + continue; + } + + jmem_cpointer_t prop_iter_cp = obj_iter_p->u1.property_list_cp; + + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + ecma_property_hashmap_free (obj_iter_p); + } + } + } + + obj_iter_cp = obj_iter_p->gc_next_cp; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + jmem_pools_collect_empty (); + return; + } + else if (JERRY_UNLIKELY (pressure == JMEM_PRESSURE_FULL)) + { + jerry_fatal (JERRY_FATAL_OUT_OF_MEMORY); + } + else + { + JERRY_ASSERT (pressure == JMEM_PRESSURE_NONE); + JERRY_UNREACHABLE (); + } +} /* ecma_free_unused_memory */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.h new file mode 100644 index 00000000..94a6d2a9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-gc.h @@ -0,0 +1,54 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_GC_H +#define ECMA_GC_H + +#include "ecma-globals.h" + +#include "jmem.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmagc Garbage collector + * @{ + */ + +/** + * Free option flags + */ +typedef enum +{ + ECMA_GC_FREE_NO_OPTIONS = 0, /**< no options */ + ECMA_GC_FREE_SECOND_PROPERTY = (1 << 0), /**< free second property of a property pair */ + ECMA_GC_FREE_REFERENCES = (1 << 1), /**< free references */ +} ecma_gc_free_options_t; + +void ecma_init_gc_info (ecma_object_t *object_p); +void ecma_ref_object (ecma_object_t *object_p); +void ecma_ref_object_inline (ecma_object_t *object_p); +void ecma_deref_object (ecma_object_t *object_p); +void ecma_gc_free_property (ecma_object_t *object_p, ecma_property_pair_t *prop_pair_p, uint32_t options); +void ecma_gc_free_properties (ecma_object_t *object_p, uint32_t options); +void ecma_gc_run (void); +void ecma_free_unused_memory (jmem_pressure_t pressure); + +/** + * @} + * @} + */ + +#endif /* !ECMA_GC_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-globals.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-globals.h new file mode 100644 index 00000000..acfea5f3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-globals.h @@ -0,0 +1,2271 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_GLOBALS_H +#define ECMA_GLOBALS_H + +#include "jerry-config.h" +#include "ecma-errors.h" +#include "jmem.h" +#include "jrt.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmatypes ECMA types + * @{ + * + * \addtogroup compressedpointer Compressed pointer + * @{ + */ + +/** + * The NULL value for compressed pointers + */ +#define ECMA_NULL_POINTER JMEM_CP_NULL + +#if defined(JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY) + +/** + * JMEM_ALIGNMENT_LOG aligned pointers can be stored directly in ecma_value_t + */ +#define ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + +#endif /* JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY */ + +/** + * @} + */ + +/** + * JerryScript status flags. + */ +typedef enum +{ + ECMA_STATUS_API_ENABLED = (1u << 0), /**< api available */ + ECMA_STATUS_DIRECT_EVAL = (1u << 1), /**< eval is called directly */ +#if JERRY_PROPERTY_HASHMAP + ECMA_STATUS_HIGH_PRESSURE_GC = (1u << 2), /**< last gc was under high pressure */ +#endif /* JERRY_PROPERTY_HASHMAP */ + ECMA_STATUS_EXCEPTION = (1u << 3), /**< last exception is a normal exception */ + ECMA_STATUS_ABORT = (1u << 4), /**< last exception is an abort */ + ECMA_STATUS_ERROR_UPDATE = (1u << 5), /**< the error_object_created_callback_p is called */ +#if JERRY_VM_THROW + ECMA_STATUS_ERROR_THROWN = (1u << 6), /**< the vm_throw_callback_p is called */ +#endif /* JERRY_VM_THROW */ +} ecma_status_flag_t; + +/** + * Type of ecma value + */ +typedef enum +{ + ECMA_TYPE_DIRECT = 0, /**< directly encoded value, a 28 bit signed integer or a simple value */ + ECMA_TYPE_STRING = 1, /**< pointer to description of a string */ + ECMA_TYPE_FLOAT = 2, /**< pointer to a 64 or 32 bit floating point number */ + ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */ + ECMA_TYPE_SYMBOL = 4, /**< pointer to description of a symbol */ + ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */ + ECMA_TYPE_BIGINT = 6, /**< pointer to a bigint primitive */ + ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */ + ECMA_TYPE_SNAPSHOT_OFFSET = ECMA_TYPE_ERROR, /**< offset to a snapshot number/string */ + ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */ +} ecma_type_t; + +/** + * Option flags for parser_parse_script and internal flags for global_status_flags in parser context. + */ +typedef enum +{ + ECMA_PARSE_NO_OPTS = 0, /**< no options passed */ + ECMA_PARSE_STRICT_MODE = (1u << 0), /**< enable strict mode, must be same as PARSER_IS_STRICT */ + ECMA_PARSE_MODULE = (1u << 1), /**< module is parsed */ + ECMA_PARSE_EVAL = (1u << 2), /**< eval is called */ + ECMA_PARSE_DIRECT_EVAL = (1u << 3), /**< eval is called directly (ECMA-262 v5, 15.1.2.1.1) */ + ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 4), /**< a class constructor is being parsed */ + + /* These five status flags must be in this order. The first four are also parser status flags. + * See PARSER_SAVE_STATUS_FLAGS / PARSER_RESTORE_STATUS_FLAGS. */ + ECMA_PARSE_ALLOW_SUPER = (1u << 5), /**< allow super property access */ + ECMA_PARSE_ALLOW_SUPER_CALL = (1u << 6), /**< allow super constructor call */ + ECMA_PARSE_FUNCTION_IS_PARSING_ARGS = (1u << 7), /**< set when parsing function arguments */ + ECMA_PARSE_INSIDE_CLASS_FIELD = (1u << 8), /**< a class field is being parsed */ + ECMA_PARSE_ALLOW_NEW_TARGET = (1u << 9), /**< allow new.target access */ + ECMA_PARSE_FUNCTION_CONTEXT = (1u << 10), /**< function context is present (ECMA_PARSE_DIRECT_EVAL must be set) */ + + ECMA_PARSE_HAS_SOURCE_VALUE = (1u << 11), /**< source_p points to a value list + * and the first value is the source code */ + ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE = (1u << 12), /**< source_p points to a value list + * and the second value is the argument list */ + ECMA_PARSE_GENERATOR_FUNCTION = (1u << 13), /**< generator function is parsed */ + ECMA_PARSE_ASYNC_FUNCTION = (1u << 14), /**< async function is parsed */ + + /* These flags are internally used by the parser. */ + ECMA_PARSE_INTERNAL_FREE_SOURCE = (1u << 15), /**< free source_p data */ + ECMA_PARSE_INTERNAL_FREE_ARG_LIST = (1u << 16), /**< free arg_list_p data */ + ECMA_PARSE_INTERNAL_PRE_SCANNING = (1u << 17), /**< the parser is in pre-scanning mode */ +#if JERRY_MODULE_SYSTEM + ECMA_PARSE_INTERNAL_HAS_IMPORT_META = (1u << 18), /**< module has import.meta expression */ +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_FUNCTION_TO_STRING + ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 19), /**< source has 4 byte marker */ +#endif /* JERRY_FUNCTION_TO_STRING */ +#ifndef JERRY_NDEBUG + /** + * This flag represents an error in for in/of statements, which cannot be set + * if the parsing is completed successfully. + */ + ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR = (1u << 30), +#endif /* !JERRY_NDEBUG */ +} ecma_parse_opts_t; + +/** + * Description of an ecma value + * + * Bit-field structure: type (3) | value (29) + */ +typedef uint32_t ecma_value_t; + +/** + * Type for directly encoded integer numbers in JerryScript. + */ +typedef int32_t ecma_integer_value_t; + +/** + * Mask for ecma types in ecma_value_t + */ +#define ECMA_VALUE_TYPE_MASK 0x7u + +/** + * Shift for value part in ecma_value_t + */ +#define ECMA_VALUE_SHIFT 3 + +/** + * Mask for directly encoded values + */ +#define ECMA_DIRECT_TYPE_MASK ((1u << ECMA_VALUE_SHIFT) | ECMA_VALUE_TYPE_MASK) + +/** + * Ecma integer value type + */ +#define ECMA_DIRECT_TYPE_INTEGER_VALUE ((0u << ECMA_VALUE_SHIFT) | ECMA_TYPE_DIRECT) + +/** + * Ecma simple value type + */ +#define ECMA_DIRECT_TYPE_SIMPLE_VALUE ((1u << ECMA_VALUE_SHIFT) | ECMA_TYPE_DIRECT) + +/** + * Shift for directly encoded values in ecma_value_t + */ +#define ECMA_DIRECT_SHIFT 4 + +/** + * ECMA make simple value + */ +#define ECMA_MAKE_VALUE(value) ((((ecma_value_t) (value)) << ECMA_DIRECT_SHIFT) | ECMA_DIRECT_TYPE_SIMPLE_VALUE) + +/** + * Simple ecma values + */ +enum +{ + /** + * Empty value is implementation defined value, used for representing: + * - empty (uninitialized) values + * - immutable binding values + * - special register or stack values for vm + */ + ECMA_VALUE_EMPTY = ECMA_MAKE_VALUE (0), /**< uninitialized value */ + ECMA_VALUE_ERROR = ECMA_MAKE_VALUE (1), /**< an error is currently thrown */ + ECMA_VALUE_FALSE = ECMA_MAKE_VALUE (2), /**< boolean false */ + ECMA_VALUE_TRUE = ECMA_MAKE_VALUE (3), /**< boolean true */ + ECMA_VALUE_UNDEFINED = ECMA_MAKE_VALUE (4), /**< undefined value */ + ECMA_VALUE_NULL = ECMA_MAKE_VALUE (5), /**< null value */ + ECMA_VALUE_UNINITIALIZED = ECMA_MAKE_VALUE (6), /**< a special value for uninitialized let/const declarations */ + ECMA_VALUE_NOT_FOUND = ECMA_MAKE_VALUE (7), /**< a special value returned by + * ecma_op_object_find */ + /* Values for controlling the VM */ + ECMA_VALUE_ARRAY_HOLE = ECMA_MAKE_VALUE (8), /**< array hole, used for + * initialization of an array literal */ + ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (9), /**< register reference, + * a special "base" value for vm */ + ECMA_VALUE_RELEASE_LEX_ENV = ECMA_MAKE_VALUE (10), /**< if this error remains on the stack when an exception occurs + the top lexical environment of the VM frame should be popped */ + ECMA_VALUE_SPREAD_ELEMENT = ECMA_MAKE_VALUE (11), /**< a special value for spread elements in array initialization + * or function call argument list */ + /* Other values */ + ECMA_VALUE_ARGUMENT_NO_TRACK = ECMA_MAKE_VALUE (12), /**< represents not-tracked arguments formal parameter */ + ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: sync iterator is requested */ + ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (14), /**< option for ecma_op_get_iterator: async iterator is requested */ +#if JERRY_BUILTIN_GLOBAL_THIS + ECMA_VALUE_GLOBAL_THIS = ECMA_MAKE_VALUE (15), /**< globalThis built-in */ +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ +}; + +#if !JERRY_NUMBER_TYPE_FLOAT64 +/** + * Maximum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MAX 0x7fffff +/** + * Maximum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MAX_SHIFTED 0x7fffff0 +#else /* JERRY_NUMBER_TYPE_FLOAT64 */ +/** + * Maximum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MAX 0x7ffffff +/** + * Maximum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MAX_SHIFTED 0x7ffffff0 +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +#if !JERRY_NUMBER_TYPE_FLOAT64 +/** + * Minimum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MIN -0x7fffff +/** + * Minimum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MIN_SHIFTED -0x7fffff0 +#else /* JERRY_NUMBER_TYPE_FLOAT64 */ +/** + * Minimum integer number for an ecma value + */ +#define ECMA_INTEGER_NUMBER_MIN -0x8000000 +/** + * Minimum integer number for an ecma value (shifted left with ECMA_DIRECT_SHIFT) + */ +#define ECMA_INTEGER_NUMBER_MIN_SHIFTED (-0x7fffffff - 1) /* -0x80000000 */ +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +#if ECMA_DIRECT_SHIFT != 4 +#error "Please update ECMA_INTEGER_NUMBER_MIN/MAX_SHIFTED according to the new value of ECMA_DIRECT_SHIFT." +#endif /* ECMA_DIRECT_SHIFT != 4 */ + +/** + * Checks whether the integer number is in the integer number range. + */ +#define ECMA_IS_INTEGER_NUMBER(num) (ECMA_INTEGER_NUMBER_MIN <= (num) && (num) <= ECMA_INTEGER_NUMBER_MAX) + +/** + * Maximum integer number, which if squared, still fits in ecma_integer_value_t + */ +#if !JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_INTEGER_MULTIPLY_MAX 0xb50 +#else /* JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_INTEGER_MULTIPLY_MAX 0x2d41 +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Checks whether the error flag is set. + */ +#define ECMA_IS_VALUE_ERROR(value) (JERRY_UNLIKELY ((value) == ECMA_VALUE_ERROR)) + +/** + * Callback which tells whether the ECMAScript execution should be stopped. + */ +typedef ecma_value_t (*ecma_vm_exec_stop_callback_t) (void *user_p); + +/** + * Forward definition of jerry_call_info_t. + */ +struct jerry_call_info_t; + +/** + * Type of an external function handler. + */ +typedef ecma_value_t (*ecma_native_handler_t) (const struct jerry_call_info_t *call_info_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +/** + * Representation of native pointer data. + */ +typedef struct +{ + void *native_p; /**< points to the data of the object */ + jerry_object_native_info_t *native_info_p; /**< native info */ +} ecma_native_pointer_t; + +/** + * Representation of native pointer data chain. + */ +typedef struct ecma_native_pointer_chain_t +{ + ecma_native_pointer_t data; /**< pointer data */ + struct ecma_native_pointer_chain_t *next_p; /**< next in the list */ +} ecma_native_pointer_chain_t; + +/** + * Representation for class constructor environment record. + */ +typedef struct +{ + ecma_value_t this_binding; /**< this binding */ + ecma_value_t function_object; /**< function object */ +} ecma_environment_record_t; + +/** + * Property list: + * The property list of an object is a chain list of various items. + * The type of each item is stored in the first byte of the item. + * + * The most common item is the property pair, which contains two + * ecmascript properties. It is also important, that after the + * first property pair, only property pair items are allowed. + * + * Example for other items is property name hash map, or array of items. + */ + +/** + * Property name listing options. + */ +typedef enum +{ + ECMA_LIST_NO_OPTS = (0), /**< no options are provided */ + ECMA_LIST_ARRAY_INDICES = (1 << 0), /**< exclude properties with names + * that are not indices */ + ECMA_LIST_ENUMERABLE = (1 << 1), /**< exclude non-enumerable properties */ + ECMA_LIST_PROTOTYPE = (1 << 2), /**< list properties from prototype chain */ + ECMA_LIST_SYMBOLS = (1 << 3), /**< list symbol properties */ + ECMA_LIST_SYMBOLS_ONLY = (1 << 4), /**< list symbol properties only */ + ECMA_LIST_CONVERT_FAST_ARRAYS = (1 << 5), /**< after listing the properties convert + * the fast access mode array back to normal array */ +} ecma_list_properties_options_t; + +/** + * Enumerable property name listing options. + */ +typedef enum +{ + ECMA_ENUMERABLE_PROPERTY_KEYS, /**< List only property names */ + ECMA_ENUMERABLE_PROPERTY_VALUES, /**< List only property values */ + ECMA_ENUMERABLE_PROPERTY_ENTRIES, /**< List both propery names and values */ + + ECMA_ENUMERABLE_PROPERTY__COUNT /**< Number of enumerable property listing types */ +} ecma_enumerable_property_names_options_t; + +/** + * List enumerable properties and include the prototype chain. + */ +#define ECMA_LIST_ENUMERABLE_PROTOTYPE (ECMA_LIST_ENUMERABLE | ECMA_LIST_PROTOTYPE) + +/** + * Property flag list. Several flags are alias + */ +typedef enum +{ + ECMA_PROPERTY_FLAG_CONFIGURABLE = (1u << 0), /**< property is configurable */ + ECMA_PROPERTY_FLAG_ENUMERABLE = (1u << 1), /**< property is enumerable */ + ECMA_PROPERTY_FLAG_WRITABLE = (1u << 2), /**< property is writable */ + ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL = (1u << 2), /**< only one external pointer is assigned to this object */ + ECMA_PROPERTY_FLAG_DELETED = (1u << 3), /**< property is deleted */ + ECMA_PROPERTY_FLAG_BUILT_IN = (1u << 3), /**< property is defined by the ECMAScript standard */ + ECMA_FAST_ARRAY_FLAG = (1u << 3), /**< array is fast array */ + ECMA_PROPERTY_FLAG_LCACHED = (1u << 4), /**< property is lcached */ + ECMA_ARRAY_TEMPLATE_LITERAL = (1u << 4), /**< array is a template literal constructed by the parser */ + ECMA_PROPERTY_FLAG_DATA = (1u << 5), /**< property contains data */ + /* The last two bits contains an ECMA_DIRECT_STRING value. */ +} ecma_property_flags_t; + +/** + * Property flags configurable, enumerable, writable. + */ +#define ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE \ + (ECMA_PROPERTY_FLAG_CONFIGURABLE | ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flags configurable, enumerable. + */ +#define ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE (ECMA_PROPERTY_FLAG_CONFIGURABLE | ECMA_PROPERTY_FLAG_ENUMERABLE) + +/** + * Property flags configurable, enumerable. + */ +#define ECMA_PROPERTY_CONFIGURABLE_WRITABLE (ECMA_PROPERTY_FLAG_CONFIGURABLE | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flag built-in. + */ +#define ECMA_PROPERTY_BUILT_IN_FIXED (ECMA_PROPERTY_FLAG_BUILT_IN) + +/** + * Property flags enumerable, writable. + */ +#define ECMA_PROPERTY_ENUMERABLE_WRITABLE (ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flags built-in, configurable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/** + * Property flags built-in, configurable, enumerable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE \ + (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) + +/** + * Property flags built-in, configurable, writable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/** + * Property flags built-in, writable. + */ +#define ECMA_PROPERTY_BUILT_IN_WRITABLE (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_FLAG_WRITABLE) + +/** + * Property flags built-in, configurable, enumerable, writable. + */ +#define ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE \ + (ECMA_PROPERTY_FLAG_BUILT_IN | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +/** + * No attributes can be changed for this property. + */ +#define ECMA_PROPERTY_FIXED 0 + +/** + * Default flag of length property. + */ +#define ECMA_PROPERTY_FLAG_DEFAULT_LENGTH ECMA_PROPERTY_FLAG_CONFIGURABLE + +/** + * Shift for property name part. + */ +#define ECMA_PROPERTY_NAME_TYPE_SHIFT 6 + +/** + * Type of hash-map property. + */ +#define ECMA_PROPERTY_TYPE_HASHMAP (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT) + +/** + * Type of deleted property. + */ +#define ECMA_PROPERTY_TYPE_DELETED \ + (ECMA_PROPERTY_FLAG_DELETED | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Type of property not found. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND ECMA_PROPERTY_TYPE_HASHMAP + +/** + * Type of property not found and no more searching in the proto chain. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP ECMA_PROPERTY_TYPE_DELETED + +/** + * Type of property not found and an exception is thrown. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW \ + (ECMA_PROPERTY_FLAG_LCACHED | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Checks whether a property is not found. + */ +#define ECMA_PROPERTY_IS_FOUND(property) \ + (((property) & (ECMA_PROPERTY_FLAG_DATA | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT))) \ + != (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Abstract property representation. + * + * A property is a type_and_flags byte and an ecma_value_t value pair. + * This pair is represented by a single pointer in JerryScript. Although + * a packed struct would only consume sizeof(ecma_value_t)+1 memory + * bytes, accessing such structure is inefficient from the CPU viewpoint + * because the value is not naturally aligned. To improve performance, + * two type bytes and values are packed together. The memory layout is + * the following: + * + * [type 1, type 2, unused byte 1, unused byte 2][value 1][value 2] + * + * The unused two bytes are used to store a compressed pointer for the + * next property pair. + * + * The advantage of this layout is that the value reference can be computed + * from the property address. However, property pointers cannot be compressed + * anymore. + */ +typedef uint8_t ecma_property_t; /**< ecma_property_types_t (3 bit) and ecma_property_flags_t */ + +/** + * Number of items in a property pair. + */ +#define ECMA_PROPERTY_PAIR_ITEM_COUNT 2 + +/** + * Property header for all items in a property list. + */ +typedef struct +{ +#if JERRY_CPOINTER_32_BIT + jmem_cpointer_t next_property_cp; /**< next cpointer */ +#endif /* JERRY_CPOINTER_32_BIT */ + ecma_property_t types[ECMA_PROPERTY_PAIR_ITEM_COUNT]; /**< two property type slot. The first represent + * the type of this property (e.g. property pair) */ +#if JERRY_CPOINTER_32_BIT + uint16_t padding; /**< an unused value */ +#else /* !JERRY_CPOINTER_32_BIT */ + jmem_cpointer_t next_property_cp; /**< next cpointer */ +#endif /* JERRY_CPOINTER_32_BIT */ +} ecma_property_header_t; + +/** + * Pair of pointers - to property's getter and setter + */ +typedef struct +{ + jmem_cpointer_t getter_cp; /**< compressed pointer to getter object */ + jmem_cpointer_t setter_cp; /**< compressed pointer to setter object */ +} ecma_getter_setter_pointers_t; + +/** + * Property data. + */ +typedef union +{ + ecma_value_t value; /**< value of a property */ +#if JERRY_CPOINTER_32_BIT + jmem_cpointer_t getter_setter_pair_cp; /**< cpointer to getter setter pair */ +#else /* !JERRY_CPOINTER_32_BIT */ + ecma_getter_setter_pointers_t getter_setter_pair; /**< getter setter pair */ +#endif /* JERRY_CPOINTER_32_BIT */ +} ecma_property_value_t; + +/** + * Property pair. + */ +typedef struct +{ + ecma_property_header_t header; /**< header of the property */ + ecma_property_value_t values[ECMA_PROPERTY_PAIR_ITEM_COUNT]; /**< property value slots */ + jmem_cpointer_t names_cp[ECMA_PROPERTY_PAIR_ITEM_COUNT]; /**< property name slots */ +} ecma_property_pair_t; + +/** + * Get property name type. + */ +#define ECMA_PROPERTY_GET_NAME_TYPE(property) ((property) >> ECMA_PROPERTY_NAME_TYPE_SHIFT) + +/** + * Returns true if the property pointer is a property pair. + */ +#define ECMA_PROPERTY_IS_PROPERTY_PAIR(property_header_p) ((property_header_p)->types[0] != ECMA_PROPERTY_TYPE_HASHMAP) + +/** + * Property value of all internal properties + */ +#define ECMA_PROPERTY_INTERNAL (ECMA_PROPERTY_FLAG_DATA | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Checks whether a property is internal property + */ +#define ECMA_PROPERTY_IS_INTERNAL(property) ((property) >= ECMA_PROPERTY_INTERNAL) + +/** + * Checks whether a property is raw data or accessor property + */ +#define ECMA_PROPERTY_IS_RAW(property) ((property) < (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) + +/** + * Checks whether a property is raw data property (should only be used in assertions) + */ +#define ECMA_PROPERTY_IS_RAW_DATA(property) \ + (((property) &ECMA_PROPERTY_FLAG_DATA) && (property) < ECMA_PROPERTY_INTERNAL) + +/** + * Create internal property. + */ +#define ECMA_CREATE_INTERNAL_PROPERTY(object_p, name_p, property_p, property_value_p) \ + do \ + { \ + (property_value_p) = ecma_create_named_data_property ((object_p), (name_p), 0, &(property_p)); \ + JERRY_ASSERT (*(property_p) == ECMA_PROPERTY_INTERNAL); \ + } while (0) + +/** + * Property type of all virtual properties + */ +#define ECMA_PROPERTY_VIRTUAL ECMA_PROPERTY_INTERNAL + +/** + * Checks whether a property is virtual property + */ +#define ECMA_PROPERTY_IS_VIRTUAL(property) ECMA_PROPERTY_IS_INTERNAL (property) + +/** + * Returns true if the property is named property. + */ +#define ECMA_PROPERTY_IS_NAMED_PROPERTY(property) \ + ((property) < ECMA_PROPERTY_TYPE_HASHMAP || (property) >= ECMA_PROPERTY_INTERNAL) + +/** + * Add the offset part to a property for computing its property data pointer. + */ +#define ECMA_PROPERTY_VALUE_ADD_OFFSET(property_p) \ + ((uintptr_t) ((((uint8_t *) (property_p)) + (sizeof (ecma_property_value_t) * 2 - 1)))) + +/** + * Align the property for computing its property data pointer. + */ +#define ECMA_PROPERTY_VALUE_DATA_PTR(property_p) \ + (ECMA_PROPERTY_VALUE_ADD_OFFSET (property_p) & ~(sizeof (ecma_property_value_t) - 1)) + +/** + * Compute the property data pointer of a property. + * The property must be part of a property pair. + */ +#define ECMA_PROPERTY_VALUE_PTR(property_p) ((ecma_property_value_t *) ECMA_PROPERTY_VALUE_DATA_PTR (property_p)) + +/** + * Property reference. It contains the value pointer + * for real, and the value itself for virtual properties. + */ +typedef union +{ + ecma_property_value_t *value_p; /**< property value pointer for real properties */ + ecma_value_t virtual_value; /**< property value for virtual properties */ +} ecma_property_ref_t; + +/** + * Extended property reference, which also contains the + * property descriptor pointer for real properties. + */ +typedef struct +{ + ecma_property_ref_t property_ref; /**< property reference */ + ecma_property_t *property_p; /**< property descriptor pointer for real properties */ +} ecma_extended_property_ref_t; + +/** + * Option flags for ecma_op_object_get_property. + */ +typedef enum +{ + ECMA_PROPERTY_GET_NO_OPTIONS = 0, /**< no option flags for ecma_op_object_get_property */ + ECMA_PROPERTY_GET_VALUE = 1u << 0, /**< fill virtual_value field for virtual properties */ + ECMA_PROPERTY_GET_EXT_REFERENCE = 1u << 1, /**< get extended reference to the property */ +} ecma_property_get_option_bits_t; + +/** + * Internal object types. + */ +typedef enum +{ + ECMA_OBJECT_TYPE_GENERAL = 0, /**< all objects that are not belongs to the sub-types below */ + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL = 1, /**< built-in general object */ + ECMA_OBJECT_TYPE_CLASS = 2, /**< Objects with class property */ + ECMA_OBJECT_TYPE_BUILT_IN_CLASS = 3, /**< built-in object with class property */ + ECMA_OBJECT_TYPE_ARRAY = 4, /**< Array object (15.4) */ + ECMA_OBJECT_TYPE_BUILT_IN_ARRAY = 5, /**< Built-in array object */ + ECMA_OBJECT_TYPE_PROXY = 6, /**< Proxy object ECMAScript v6 26.2 */ + /* Note: these 4 types must be in this order. See IsCallable operation. */ + ECMA_OBJECT_TYPE_FUNCTION = 7, /**< Function objects (15.3), created through 13.2 routine */ + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION = 8, /**< Native built-in function object */ + ECMA_OBJECT_TYPE_BOUND_FUNCTION = 9, /**< Function objects (15.3), created through 15.3.4.5 routine */ + ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION = 10, /**< implicit class constructor function */ + ECMA_OBJECT_TYPE_NATIVE_FUNCTION = 11, /**< Native function object */ + + ECMA_OBJECT_TYPE__MAX /**< maximum value */ +} ecma_object_type_t; + +/** + * Base object types without built-in flag. + * + * Note: + * only these types can be checked with ecma_get_object_base_type. + */ +typedef enum +{ + ECMA_OBJECT_BASE_TYPE_GENERAL = ECMA_OBJECT_TYPE_GENERAL, /**< generic objects */ + ECMA_OBJECT_BASE_TYPE_CLASS = ECMA_OBJECT_TYPE_CLASS, /**< Objects with class property */ + ECMA_OBJECT_BASE_TYPE_ARRAY = ECMA_OBJECT_TYPE_ARRAY, /**< Array object (15.4) */ +} ecma_object_base_type_t; + +/** + * Types of objects with class property. + * + * Note: + * when this type is changed, both ecma_class_object_magic_string_id + * and jerry_class_object_type must be updated as well + */ +typedef enum +{ + /* These objects require custom property resolving. */ + ECMA_OBJECT_CLASS_STRING, /**< String Object (ECMAScript v5.1, 4.3.18) */ + ECMA_OBJECT_CLASS_ARGUMENTS, /**< Arguments object (10.6) */ +#if JERRY_BUILTIN_TYPEDARRAY + ECMA_OBJECT_CLASS_TYPEDARRAY, /**< TypedArray which does NOT need extra space to store length and offset */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + ECMA_OBJECT_CLASS_MODULE_NAMESPACE, /**< Module Namespace (ECMAScript v11, 9.4.6) */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* These objects are marked by Garbage Collector. */ + ECMA_OBJECT_CLASS_GENERATOR, /**< Generator object (ECMAScript v6, 25.2) */ + ECMA_OBJECT_CLASS_ASYNC_GENERATOR, /**< Async generator object (ECMAScript v11, 25.3) */ + ECMA_OBJECT_CLASS_ARRAY_ITERATOR, /**< Array iterator object (ECMAScript v6, 22.1.5.1) */ + ECMA_OBJECT_CLASS_SET_ITERATOR, /**< Set iterator object (ECMAScript v6, 23.2.5.1) */ + ECMA_OBJECT_CLASS_MAP_ITERATOR, /**< Map iterator object (ECMAScript v6, 23.1.5.1) */ +#if JERRY_BUILTIN_REGEXP + ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR, /** RegExp string iterator object (ECMAScript v11, 21.2.7) */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM + ECMA_OBJECT_CLASS_MODULE, /**< Module (ECMAScript v6, 15.2) */ +#endif /* JERRY_MODULE_SYSTEM */ + ECMA_OBJECT_CLASS_PROMISE, /**< Promise (ECMAScript v6, 25.4) */ + ECMA_OBJECT_CLASS_PROMISE_CAPABILITY, /**< Promise capability (ECMAScript v6, 25.4.1.1) */ + ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR, /**< AsyncFromSyncIterator (ECMAScript v11, 25.1.4) */ +#if JERRY_BUILTIN_DATAVIEW + ECMA_OBJECT_CLASS_DATAVIEW, /**< DataView (ECMAScript v6, 24.2) */ +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + ECMA_OBJECT_CLASS_CONTAINER, /**< Container (Map, WeakMap, Set, WeakSet) */ +#endif /* JERRY_BUILTIN_CONTAINER */ + + /* Normal objects. */ + ECMA_OBJECT_CLASS_BOOLEAN, /**< Boolean Object (ECMAScript v5.1, 4.3.15) */ + ECMA_OBJECT_CLASS_NUMBER, /**< Number Object (ECMAScript v5.1, 4.3.21) */ + ECMA_OBJECT_CLASS_ERROR, /**< Error Object (ECMAScript v5.1, 15.11) */ + ECMA_OBJECT_CLASS_INTERNAL_OBJECT, /**< object for internal properties */ +#if JERRY_PARSER + ECMA_OBJECT_CLASS_SCRIPT, /**< Compiled ECMAScript byte code */ +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + ECMA_OBJECT_CLASS_DATE, /**< Date Object (ECMAScript v5.1, 15.9) */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + ECMA_OBJECT_CLASS_REGEXP, /**< RegExp Object (ECMAScript v5.1, 15.10) */ +#endif /* JERRY_BUILTIN_REGEXP */ + ECMA_OBJECT_CLASS_SYMBOL, /**< Symbol object (ECMAScript v6, 4.3.27) */ + ECMA_OBJECT_CLASS_STRING_ITERATOR, /**< String iterator object (ECMAScript v6, 22.1.5.1) */ +#if JERRY_BUILTIN_TYPEDARRAY + ECMA_OBJECT_CLASS_ARRAY_BUFFER, /**< Array Buffer (ECMAScript v6, 24.1) */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, /**< Shared Array Buffer (ECMAScript v11 24.2) */ +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_BIGINT + ECMA_OBJECT_CLASS_BIGINT, /**< Bigint (ECMAScript v11, 4.3.27) */ +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_WEAKREF + ECMA_OBJECT_CLASS_WEAKREF, /**< WeakRef (Not standardized yet) */ +#endif /* JERRY_BUILTIN_WEAKREF */ + + ECMA_OBJECT_CLASS__MAX /**< maximum value */ +} ecma_object_class_type_t; + +/** + * Types of lexical environments. + */ +typedef enum +{ + /* Types between 0 - 12 are ecma_object_type_t. */ + ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 13, /**< declarative lexical environment */ + ECMA_LEXICAL_ENVIRONMENT_CLASS = 14, /**< lexical environment with class */ + ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 15, /**< object-bound lexical environment */ + + ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical + * environment type */ + ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND /**< maximum value */ +} ecma_lexical_environment_type_t; + +/** + * Types of array iterators. + */ +typedef enum +{ + ECMA_ITERATOR_KEYS, /**< keys iterator */ + ECMA_ITERATOR_VALUES, /**< values iterator */ + ECMA_ITERATOR_ENTRIES, /**< entries iterator */ + ECMA_ITERATOR__COUNT, /**< number of iterator kinds */ +} ecma_iterator_kind_t; + +/** + * Offset for JERRY_CONTEXT (status_flags) top 8 bits. + */ +#define ECMA_LOCAL_PARSE_OPTS_OFFSET ((sizeof (uint32_t) - sizeof (uint8_t)) * JERRY_BITSINBYTE) + +/** + * Set JERRY_CONTEXT (status_flags) top 8 bits to the specified 'opts'. + */ +#define ECMA_SET_LOCAL_PARSE_OPTS(opts) \ + do \ + { \ + JERRY_CONTEXT (status_flags) |= ((uint32_t) opts << ECMA_LOCAL_PARSE_OPTS_OFFSET) | ECMA_STATUS_DIRECT_EVAL; \ + } while (0) + +/** + * Get JERRY_CONTEXT (status_flags) top 8 bits. + */ +#define ECMA_GET_LOCAL_PARSE_OPTS() \ + (JERRY_CONTEXT (status_flags) >> (ECMA_LOCAL_PARSE_OPTS_OFFSET - JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER))) + +/** + * Clear JERRY_CONTEXT (status_flags) top 8 bits. + */ +#define ECMA_CLEAR_LOCAL_PARSE_OPTS() \ + do \ + { \ + JERRY_CONTEXT (status_flags) &= ((1 << ECMA_LOCAL_PARSE_OPTS_OFFSET) - 1); \ + } while (0) + +/** + * Ecma object type mask for getting the object type. + */ +#define ECMA_OBJECT_TYPE_MASK 0x00fu + +/** + * Extensible object. + */ +#define ECMA_OBJECT_FLAG_EXTENSIBLE 0x10 + +/** + * Declarative lexical environments created for non-closure code blocks + */ +#define ECMA_OBJECT_FLAG_BLOCK ECMA_OBJECT_FLAG_EXTENSIBLE + +/** + * Lexical environments with class has extra data + */ +#define ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA ECMA_OBJECT_FLAG_EXTENSIBLE + +/** + * Bitshift index for an ecma-object reference count field + */ +#define ECMA_OBJECT_REF_SHIFT 5 + +/** + * Value for increasing or decreasing the object reference counter. + */ +#define ECMA_OBJECT_REF_ONE (1u << ECMA_OBJECT_REF_SHIFT) + +#if JERRY_CPOINTER_32_BIT + +/** + * Type of the descriptor field of an object + */ +typedef uint32_t ecma_object_descriptor_t; + +#else /* !JERRY_CPOINTER_32_BIT */ + +/** + * Type of the descriptor field of an object + */ +typedef uint16_t ecma_object_descriptor_t; + +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Bitmask for an ecma-object reference count field + */ +#define ECMA_OBJECT_REF_MASK ((ecma_object_descriptor_t) (~0u << ECMA_OBJECT_REF_SHIFT)) + +/** + * Represents non-visited white object + */ +#define ECMA_OBJECT_NON_VISITED ECMA_OBJECT_REF_MASK + +/** + * Maximum value of the object reference counter (1022 / 67108862). + */ +#define ECMA_OBJECT_MAX_REF (ECMA_OBJECT_NON_VISITED - ECMA_OBJECT_REF_ONE) + +/** + * Description of ECMA-object or lexical environment + * (depending on is_lexical_environment). + */ +typedef struct +{ + /** type : 4 bit : ecma_object_type_t or ecma_lexical_environment_type_t + depending on ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV + flags : 2 bit : ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV, + ECMA_OBJECT_FLAG_EXTENSIBLE or ECMA_OBJECT_FLAG_BLOCK + refs : 10 / 26 bit (max 1022 / 67108862) */ + ecma_object_descriptor_t type_flags_refs; + + /** next in the object chain maintained by the garbage collector */ + jmem_cpointer_t gc_next_cp; + + /** compressed pointer to property list or bound object */ + union + { + jmem_cpointer_t property_list_cp; /**< compressed pointer to object's + * or declerative lexical environments's property list */ + jmem_cpointer_t bound_object_cp; /**< compressed pointer to lexical environments's the bound object */ + jmem_cpointer_t home_object_cp; /**< compressed pointer to lexical environments's the home object */ + } u1; + + /** object prototype or outer reference */ + union + { + jmem_cpointer_t prototype_cp; /**< compressed pointer to the object's prototype */ + jmem_cpointer_t outer_reference_cp; /**< compressed pointer to the lexical environments's outer reference */ + } u2; +} ecma_object_t; + +/** + * Description of built-in properties of an object. + */ +typedef struct +{ + uint8_t id; /**< built-in id */ + uint8_t routine_id; /**< routine id for built-in functions */ + /** built-in specific field */ + union + { + uint8_t length_and_bitset_size; /**< length and bit set size for generic built-ins */ + uint8_t routine_index; /**< property descriptor index for built-in routines */ + } u; + /** extra built-in info */ + union + { + uint8_t instantiated_bitset[1]; /**< instantiated property bit set for generic built-ins */ + uint8_t routine_flags; /**< flags for built-in routines */ + } u2; + +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value; /**< realm value */ +#else /* !JERRY_BUILTIN_REALMS */ + uint32_t continue_instantiated_bitset[1]; /**< bit set for instantiated properties */ +#endif /* JERRY_BUILTIN_REALMS */ +} ecma_built_in_props_t; + +/** + * Type of a built-in function handler. + */ +typedef ecma_value_t (*ecma_builtin_handler_t) (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +#if JERRY_BUILTIN_REALMS + +/** + * Number of bits available in the instantiated bitset without allocation + */ +#define ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE (8) + +#else /* !JERRY_BUILTIN_REALMS */ + +/** + * Number of bits available in the instantiated bitset without allocation + */ +#define ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE (8 + 32) + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * Builtin routine function object status flags + */ +typedef enum +{ + ECMA_BUILTIN_ROUTINE_NO_OPTS = 0, /**< No options are provided */ + ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED = (1u << 0), /**< 'length' property has been initialized */ + ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED = (1u << 1), /**< 'name' property has been initialized */ + ECMA_BUILTIN_ROUTINE_GETTER = (1u << 2), /**< this routine is getter */ + ECMA_BUILTIN_ROUTINE_SETTER = (1u << 3), /**< this routine is setter */ +} ecma_builtin_routine_flags_t; + +/** + * Start position of bit set size in length_and_bitset_size field. + */ +#define ECMA_BUILT_IN_BITSET_SHIFT 5 + +/** + * Description of extended ECMA-object. + * + * The extended object is an object with extra fields. + */ +typedef struct +{ + ecma_object_t object; /**< object header */ + + /** + * Description of extra fields. These extra fields depend on the object type. + */ + union + { + ecma_built_in_props_t built_in; /**< built-in object part */ + + /** + * Description of objects with class. + * + * Note: + * class is a reserved word in c++, so cls is used instead + */ + struct + { + uint8_t type; /**< class type of the object */ + /** + * Description of 8 bit extra fields. These extra fields depend on the type. + */ + union + { + uint8_t arguments_flags; /**< arguments object flags */ + uint8_t error_type; /**< jerry_error_t type of native error objects */ +#if JERRY_BUILTIN_DATE + uint8_t date_flags; /**< flags for date objects */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_MODULE_SYSTEM + uint8_t module_state; /**< Module state */ +#endif /* JERRY_MODULE_SYSTEM */ + uint8_t iterator_kind; /**< type of iterator */ + uint8_t regexp_string_iterator_flags; /**< flags for RegExp string iterator */ + uint8_t promise_flags; /**< Promise object flags */ +#if JERRY_BUILTIN_CONTAINER + uint8_t container_flags; /**< container object flags */ +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY + uint8_t array_buffer_flags; /**< ArrayBuffer flags */ + uint8_t typedarray_type; /**< type of typed array */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } u1; + /** + * Description of 16 bit extra fields. These extra fields depend on the type. + */ + union + { + uint16_t formal_params_number; /**< for arguments: formal parameters number */ +#if JERRY_MODULE_SYSTEM + uint16_t module_flags; /**< Module flags */ +#endif /* JERRY_MODULE_SYSTEM */ + uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */ + uint16_t executable_obj_flags; /**< executable object flags */ +#if JERRY_BUILTIN_CONTAINER + uint16_t container_id; /**< magic string id of a container */ +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY + uint16_t typedarray_flags; /**< typed array object flags */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } u2; + /** + * Description of 32 bit / value. These extra fields depend on the type. + */ + union + { + ecma_value_t value; /**< value of the object (e.g. boolean, number, string, etc.) */ + ecma_value_t target; /**< [[ProxyTarget]] or [[WeakRefTarget]] internal property */ +#if JERRY_BUILTIN_TYPEDARRAY + ecma_value_t arraybuffer; /**< for typedarray: ArrayBuffer reference */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + ecma_value_t head; /**< points to the async generator task queue head item */ + ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */ + ecma_value_t promise; /**< PromiseCapability[[Promise]] internal slot */ + ecma_value_t sync_iterator; /**< IteratorRecord [[Iterator]] internal slot for AsyncFromSyncIterator */ + ecma_value_t spread_value; /**< for spread object: spreaded element */ + int32_t tza; /**< TimeZone adjustment for date objects */ + uint32_t length; /**< length related property (e.g. length of ArrayBuffer) */ + uint32_t arguments_number; /**< for arguments: arguments number */ +#if JERRY_MODULE_SYSTEM + uint32_t dfs_ancestor_index; /**< module dfs ancestor index (ES2020 15.2.1.16) */ +#endif /* JERRY_MODULE_SYSTEM */ + } u3; + } cls; + + /** + * Description of function objects. + */ + struct + { + jmem_cpointer_tag_t scope_cp; /**< function scope */ + ecma_value_t bytecode_cp; /**< function byte code */ + } function; + + /** + * Description of array objects. + */ + struct + { + uint32_t length; /**< length property value */ + uint32_t length_prop_and_hole_count; /**< length property attributes and number of array holes in + * a fast access mode array multiplied ECMA_FAST_ACCESS_HOLE_ONE */ + } array; + + /** + * Description of bound function object. + */ + struct + { + jmem_cpointer_tag_t target_function; /**< target function */ + ecma_value_t args_len_or_this; /**< length of arguments or this value */ + } bound_function; + + /** + * Description of implicit class constructor function. + */ + struct + { + ecma_value_t script_value; /**< script value */ + uint8_t flags; /**< constructor flags */ + } constructor_function; + } u; +} ecma_extended_object_t; + +/** + * Description of built-in extended ECMA-object. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + ecma_built_in_props_t built_in; /**< built-in object part */ +} ecma_extended_built_in_object_t; + +/** + * Type of lexical environment with class + */ +typedef enum +{ + ECMA_LEX_ENV_CLASS_TYPE_MODULE, /**< module object reference */ + ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV, /**< class constructor object reference */ +} ecma_lexical_environment_class_type_t; + +/** + * Description of lexical environment with class + */ +typedef struct +{ + ecma_object_t lexical_env; /**< lexical environment header */ + uint32_t type; /**< element of ecma_lexical_environment_class_type_t */ + ecma_object_t *object_p; /**< object reference */ +} ecma_lexical_environment_class_t; + +/** + * Check whether the given lexical class environment is a module + */ +#define ECMA_LEX_ENV_CLASS_IS_MODULE(lex_env_p) \ + (((lex_env_p)->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) \ + && ((ecma_lexical_environment_class_t *) (lex_env_p))->type == ECMA_LEX_ENV_CLASS_TYPE_MODULE) + +/** + * Description of native functions + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value; /**< realm value */ +#endif /* JERRY_BUILTIN_REALMS */ + ecma_native_handler_t native_handler_cb; /**< external function */ +} ecma_native_function_t; + +/** + * Alignment for the fast access mode array length. + * The real length is aligned up for allocating the underlying buffer. + */ +#define ECMA_FAST_ARRAY_ALIGNMENT (8) + +/** + * Align the length of the fast mode array to get the allocated size of the underlying buffer + */ +#define ECMA_FAST_ARRAY_ALIGN_LENGTH(length) \ + (uint32_t) ((((length)) + ECMA_FAST_ARRAY_ALIGNMENT - 1) / ECMA_FAST_ARRAY_ALIGNMENT * ECMA_FAST_ARRAY_ALIGNMENT) + +/** + * Compiled byte code data. + */ +typedef struct +{ + uint16_t size; /**< real size >> JMEM_ALIGNMENT_LOG */ + uint16_t refs; /**< reference counter for the byte code */ + uint16_t status_flags; /**< various status flags: + * CBC_IS_FUNCTION check tells whether the byte code + * is function or regular expression. + * If function, the other flags must be CBC_CODE_FLAGS... + * If regexp, the other flags must be RE_FLAG... */ +} ecma_compiled_code_t; + +/** + * Description of bound function objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object header */ + ecma_value_t target_length; /**< length of target function */ +} ecma_bound_function_t; + +#if JERRY_SNAPSHOT_EXEC + +/** + * Description of static function objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + const ecma_compiled_code_t *bytecode_p; /**< real byte code pointer */ +} ecma_static_function_t; + +#endif /* JERRY_SNAPSHOT_EXEC */ + +/** + * Description of arrow function objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object header */ + ecma_value_t this_binding; /**< value of 'this' binding */ + ecma_value_t new_target; /**< value of new.target */ +} ecma_arrow_function_t; + +#if JERRY_SNAPSHOT_EXEC + +/** + * Description of static arrow function objects. + */ +typedef struct +{ + ecma_arrow_function_t header; + const ecma_compiled_code_t *bytecode_p; +} ecma_static_arrow_function_t; + +#endif /* JERRY_SNAPSHOT_EXEC */ + +#if JERRY_BUILTIN_CONTAINER +/** + * Flags for container objects + */ +typedef enum +{ + ECMA_CONTAINER_FLAGS_EMPTY = (0), /** empty flags */ + ECMA_CONTAINER_FLAGS_WEAK = (1 << 0) /** container object is weak */ +} ecma_container_flags_t; + +/** + * Description of map collection. + */ +typedef struct +{ + ecma_value_t key; /**< key value */ + ecma_value_t value; /**< value of the key */ +} ecma_container_pair_t; + +/** + * Size of a single element (in ecma_value_t unit). + */ +#define ECMA_CONTAINER_VALUE_SIZE 1 + +/** + * Size of a key - value pair (in ecma_value_t unit). + */ +#define ECMA_CONTAINER_PAIR_SIZE 2 + +/** + * Size of the internal buffer. + */ +#define ECMA_CONTAINER_GET_SIZE(container_p) (container_p->buffer_p[0]) + +/** + * Remove the size field of the internal buffer. + */ +#define ECMA_CONTAINER_SET_SIZE(container_p, size) (container_p->buffer_p[0] = (ecma_value_t) (size)) + +/** + * Number of entries of the internal buffer. + */ +#define ECMA_CONTAINER_ENTRY_COUNT(collection_p) (collection_p->item_count - 1) + +/** + * Pointer to the first entry of the internal buffer. + */ +#define ECMA_CONTAINER_START(collection_p) (collection_p->buffer_p + 1) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +/** + * Description of ECMA property descriptor + * + * See also: ECMA-262 v5, 8.10. + * + * Note: + * If a component of descriptor is undefined then corresponding + * field should contain it's default value. + */ +typedef struct +{ + uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ + ecma_value_t value; /**< [[Value]] */ + ecma_object_t *get_p; /**< [[Get]] */ + ecma_object_t *set_p; /**< [[Set]] */ +} ecma_property_descriptor_t; + +/** + * Bitfield which represents a namedata property options in an ecma_property_descriptor_t + * Attributes: + * - is_get_defined, is_set_defined : false + * - is_configurable, is_writable, is_enumerable : undefined (false) + * - is_throw : undefined (false) + * - is_value_defined : true + * - is_configurable_defined, is_writable_defined, is_enumerable_defined : true + */ +#define ECMA_NAME_DATA_PROPERTY_DESCRIPTOR_BITS \ + ((uint16_t) (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED \ + | JERRY_PROP_IS_WRITABLE_DEFINED)) + +/** + * Bitmask to get a the physical property flags from an ecma_property_descriptor + */ +#define ECMA_PROPERTY_FLAGS_MASK \ + ((uint16_t) (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_WRITABLE)) + +/** + * Description of an ecma-number + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +typedef double ecma_number_t; +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +typedef float ecma_number_t; +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Convert double to an ecma-number. + */ +#define DOUBLE_TO_ECMA_NUMBER_T(value) ((ecma_number_t) (value)) + +/** + * Value '0' of ecma_number_t + */ +#define ECMA_NUMBER_ZERO ((ecma_number_t) 0.0f) + +/** + * Value '1' of ecma_number_t + */ +#define ECMA_NUMBER_ONE ((ecma_number_t) 1.0f) + +/** + * Value '2' of ecma_number_t + */ +#define ECMA_NUMBER_TWO ((ecma_number_t) 2.0f) + +/** + * Value '0.5' of ecma_number_t + */ +#define ECMA_NUMBER_HALF ((ecma_number_t) 0.5f) + +/** + * Value '-1' of ecma_number_t + */ +#define ECMA_NUMBER_MINUS_ONE ((ecma_number_t) -1.0f) + +/** + * Maximum number of characters in string representation of ecma-number + */ +#define ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER 64 + +/** + * Maximum number of characters in string representation of ecma-uint32 + */ +#define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 10 + +/** + * String is not a valid array index. + */ +#define ECMA_STRING_NOT_ARRAY_INDEX UINT32_MAX + +/** + * Ecma-collection: a growable list of ecma-values. + */ +typedef struct +{ + uint32_t item_count; /**< number of items in the collection */ + uint32_t capacity; /**< number of items can be stored in the underlying buffer */ + ecma_value_t *buffer_p; /**< underlying data buffer */ +} ecma_collection_t; + +/** + * Initial capacity of an ecma-collection + */ +#define ECMA_COLLECTION_INITIAL_CAPACITY 4 + +/** + * Ecma-collenction grow factor when the collection underlying buffer need to be reallocated + */ +#define ECMA_COLLECTION_GROW_FACTOR (ECMA_COLLECTION_INITIAL_CAPACITY * 2) + +/** + * Compute the total allocated size of the collection based on it's capacity + */ +#define ECMA_COLLECTION_ALLOCATED_SIZE(capacity) (uint32_t) (capacity * sizeof (ecma_value_t)) + +/** + * Initial allocated size of an ecma-collection + */ +#define ECMA_COLLECTION_INITIAL_SIZE ECMA_COLLECTION_ALLOCATED_SIZE (ECMA_COLLECTION_INITIAL_CAPACITY) + +/** + * Size shift of a compact collection + */ +#define ECMA_COMPACT_COLLECTION_SIZE_SHIFT 3 + +/** + * Get the size of the compact collection + */ +#define ECMA_COMPACT_COLLECTION_GET_SIZE(compact_collection_p) \ + ((compact_collection_p)[0] >> ECMA_COMPACT_COLLECTION_SIZE_SHIFT) + +/** + * Direct string types (2 bit). + */ +typedef enum +{ + ECMA_DIRECT_STRING_PTR = 0, /**< string is a string pointer, only used by property names */ + ECMA_DIRECT_STRING_MAGIC = 1, /**< string is a magic string */ + ECMA_DIRECT_STRING_UINT = 2, /**< string is an unsigned int */ + ECMA_DIRECT_STRING_SPECIAL = 3, /**< string is special */ +} ecma_direct_string_type_t; + +/** + * Maximum value of the immediate part of a direct magic string. + * Must be compatible with the immediate property name. + */ +#if JERRY_CPOINTER_32_BIT +#define ECMA_DIRECT_STRING_MAX_IMM 0x07ffffff +#else /* !JERRY_CPOINTER_32_BIT */ +#define ECMA_DIRECT_STRING_MAX_IMM 0x0000ffff +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Shift for direct string value part in ecma_value_t. + */ +#define ECMA_DIRECT_STRING_SHIFT (ECMA_VALUE_SHIFT + 2) + +/** + * Full mask for direct strings. + */ +#define ECMA_DIRECT_STRING_MASK ((uintptr_t) (ECMA_DIRECT_TYPE_MASK | (0x3u << ECMA_VALUE_SHIFT))) + +/** + * Create an ecma direct string. + */ +#define ECMA_CREATE_DIRECT_STRING(type, value) \ + ((uintptr_t) (ECMA_TYPE_DIRECT_STRING | ((type) << ECMA_VALUE_SHIFT) | (value) << ECMA_DIRECT_STRING_SHIFT)) + +/** + * Create an ecma direct string from the given number. + * + * Note: the given number must be less or equal than ECMA_DIRECT_STRING_MAX_IMM + */ +#define ECMA_CREATE_DIRECT_UINT32_STRING(uint32_number) \ + ((ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number)) + +/** + * Checks whether the string is direct. + */ +#define ECMA_IS_DIRECT_STRING(string_p) ((((uintptr_t) (string_p)) & 0x1) != 0) + +/** + * Checks whether the string is direct. + */ +#define ECMA_IS_DIRECT_STRING_WITH_TYPE(string_p, type) \ + ((((uintptr_t) (string_p)) & ECMA_DIRECT_STRING_MASK) == ECMA_CREATE_DIRECT_STRING (type, 0)) + +/** + * Returns the type of a direct string. + */ +#define ECMA_GET_DIRECT_STRING_TYPE(string_p) ((((uintptr_t) (string_p)) >> ECMA_VALUE_SHIFT) & 0x3) + +/** + * Shift applied to type conversions. + */ +#define ECMA_STRING_TYPE_CONVERSION_SHIFT (ECMA_PROPERTY_NAME_TYPE_SHIFT - ECMA_VALUE_SHIFT) + +/** + * Converts direct string type to property name type. + */ +#define ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE(string_p) \ + ((((uintptr_t) (string_p)) & (0x3 << ECMA_VALUE_SHIFT)) << ECMA_STRING_TYPE_CONVERSION_SHIFT) + +/** + * Returns the value of a direct string. + */ +#define ECMA_GET_DIRECT_STRING_VALUE(string_p) (((uintptr_t) (string_p)) >> ECMA_DIRECT_STRING_SHIFT) + +/** + * Maximum number of bytes that a long-utf8-string is able to store + */ +#define ECMA_STRING_SIZE_LIMIT UINT32_MAX + +typedef enum +{ + ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string + * maximum size is 2^16. */ + ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING, /**< the string is a long string or provided externally + * and only its attributes are stored. */ + ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< string representation of an uint32 number */ + ECMA_STRING_CONTAINER_HEAP_ASCII_STRING, /**< actual data is on the heap as an ASCII string + * maximum size is 2^16. */ + ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ + ECMA_STRING_CONTAINER_SYMBOL, /**< the ecma-string is a symbol */ + + ECMA_STRING_CONTAINER__MAX = ECMA_STRING_CONTAINER_SYMBOL /**< maximum value */ +} ecma_string_container_t; + +/** + * Mask for getting the container of a string. + */ +#define ECMA_STRING_CONTAINER_MASK 0x7u + +/** + * Value for increasing or decreasing the reference counter. + */ +#define ECMA_STRING_REF_ONE (1u << 4) + +/** + * Maximum value of the reference counter (4294967280). + */ +#define ECMA_STRING_MAX_REF (0xFFFFFFF0) + +/** + * Flag that identifies that the string is static which means it is stored in JERRY_CONTEXT (string_list_cp) + */ +#define ECMA_STATIC_STRING_FLAG (1 << 3) + +/** + * Set an ecma-string as static string + */ +#define ECMA_SET_STRING_AS_STATIC(string_p) (string_p)->refs_and_container |= ECMA_STATIC_STRING_FLAG + +/** + * Checks whether the ecma-string is static string + */ +#define ECMA_STRING_IS_STATIC(string_p) ((string_p)->refs_and_container & ECMA_STATIC_STRING_FLAG) + +/** + * Returns with the container type of a string. + */ +#define ECMA_STRING_GET_CONTAINER(string_desc_p) \ + ((ecma_string_container_t) ((string_desc_p)->refs_and_container & ECMA_STRING_CONTAINER_MASK)) + +/** + * Checks whether the reference counter is 1 of a string. + */ +#define ECMA_STRING_IS_REF_EQUALS_TO_ONE(string_desc_p) (((string_desc_p)->refs_and_container >> 4) == 1) + +/** + * Checks whether the reference counter is 1 of an extended primitive. + */ +#define ECMA_EXTENDED_PRIMITIVE_IS_REF_EQUALS_TO_ONE(extended_primitive_p) \ + (((extended_primitive_p)->refs_and_type >> 3) == 1) + +/** + * ECMA string-value descriptor + */ +typedef struct +{ + /** Reference counter for the string */ + uint32_t refs_and_container; + + /** + * Actual data or identifier of it's place in container (depending on 'container' field) + */ + union + { + lit_string_hash_t hash; /**< hash of the ASCII/UTF8 string */ + uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ + uint32_t uint32_number; /**< uint32-represented number placed locally in the descriptor */ + } u; +} ecma_string_t; + +/** + * ECMA UTF8 string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + uint16_t size; /**< size of this utf-8 string in bytes */ + uint16_t length; /**< length of this utf-8 string in characters */ +} ecma_short_string_t; + +/** + * Long or external CESU8 string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + const lit_utf8_byte_t *string_p; /**< string data */ + lit_utf8_size_t size; /**< size of this external string in bytes */ + lit_utf8_size_t length; /**< length of this external string in characters */ +} ecma_long_string_t; + +/** + * External UTF8 string-value descriptor + */ +typedef struct +{ + ecma_long_string_t header; /**< long string header */ + void *user_p; /**< user pointer passed to the callback when the string is freed */ +} ecma_external_string_t; + +/** + * Header size of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_HEADER_SIZE ((lit_utf8_size_t) (sizeof (ecma_string_t) + sizeof (uint8_t))) + +/** + * Get the size of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_GET_SIZE(string_p) \ + ((lit_utf8_size_t) * ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) + 1) + +/** + * Set the size of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_SET_SIZE(string_p, size) \ + (*((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) = (uint8_t) ((size) -1)) + +/** + * Get the start position of the string buffer of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + ECMA_ASCII_STRING_HEADER_SIZE) + +/** + * Get the start position of the string buffer of an ecma UTF8 string + */ +#define ECMA_SHORT_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_short_string_t)) + +/** + * Get the start position of the string buffer of an ecma long CESU8 string + */ +#define ECMA_LONG_STRING_BUFFER_START(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_long_string_t)) + +/** + * ECMA extended string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + + union + { + ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */ + ecma_value_t value; /**< original key value corresponds to the map key string */ + } u; +} ecma_extended_string_t; + +/** + * Required number of ecma values in a compact collection to represent PrivateElement + */ +#define ECMA_PRIVATE_ELEMENT_LIST_SIZE 3 + +/** + * String builder header + */ +typedef struct +{ + lit_utf8_size_t current_size; /**< size of the data in the buffer */ +} ecma_stringbuilder_header_t; + +/** + * Get pointer to the beginning of the stored string in the string builder + */ +#define ECMA_STRINGBUILDER_STRING_PTR(header_p) \ + ((lit_utf8_byte_t *) (((lit_utf8_byte_t *) header_p) + ECMA_ASCII_STRING_HEADER_SIZE)) + +/** + * Get the size of the stored string in the string builder + */ +#define ECMA_STRINGBUILDER_STRING_SIZE(header_p) \ + ((lit_utf8_size_t) (header_p->current_size - ECMA_ASCII_STRING_HEADER_SIZE)) + +/** + * String builder handle + */ +typedef struct +{ + ecma_stringbuilder_header_t *header_p; /**< pointer to header */ +} ecma_stringbuilder_t; + +#ifndef JERRY_BUILTIN_BIGINT +/** + * BigInt type. + */ +#define ECMA_EXTENDED_PRIMITIVE_BIGINT 0 +#endif /* !defined (JERRY_BUILTIN_BIGINT) */ + +/** + * Flags for exception values. + */ +typedef enum +{ + ECMA_ERROR_API_FLAG_NONE = 0, + ECMA_ERROR_API_FLAG_ABORT = (1u << 0), /**< abort flag */ + ECMA_ERROR_API_FLAG_THROW_CAPTURED = (1u << 1), /**< throw captured flag */ +} ecma_error_api_flags_t; + +/** + * Representation of a thrown value on API level. + */ +typedef struct +{ + uint32_t refs_and_type; /**< reference counter and type */ + union + { + ecma_value_t value; /**< referenced value */ + uint32_t bigint_sign_and_size; /**< BigInt properties */ + } u; +} ecma_extended_primitive_t; + +/** + * Value for increasing or decreasing the reference counter. + */ +#define ECMA_EXTENDED_PRIMITIVE_REF_ONE (1u << 3) + +/** + * Maximum value of the reference counter. + */ +#define ECMA_EXTENDED_PRIMITIVE_MAX_REF (UINT32_MAX - (ECMA_EXTENDED_PRIMITIVE_REF_ONE - 1)) + +#if JERRY_PROPERTY_HASHMAP + +/** + * The lowest state of the ecma_prop_hashmap_alloc_state counter. + * If ecma_prop_hashmap_alloc_state other other than this value, it is + * disabled. + */ +#define ECMA_PROP_HASHMAP_ALLOC_ON 0 + +/** + * The highest state of the ecma_prop_hashmap_alloc_state counter. + */ +#define ECMA_PROP_HASHMAP_ALLOC_MAX 4 + +#endif /* JERRY_PROPERTY_HASHMAP */ + +/** + * Number of values in a literal storage item + */ +#define ECMA_LIT_STORAGE_VALUE_COUNT 3 + +/** + * Literal storage item + */ +typedef struct +{ + jmem_cpointer_t next_cp; /**< cpointer ot next item */ + jmem_cpointer_t values[ECMA_LIT_STORAGE_VALUE_COUNT]; /**< list of values */ +} ecma_lit_storage_item_t; + +#if JERRY_LCACHE +/** + * Container of an LCache entry identifier + */ +#if JERRY_CPOINTER_32_BIT +typedef uint64_t ecma_lcache_hash_entry_id_t; +#else /* !JERRY_CPOINTER_32_BIT */ +typedef uint32_t ecma_lcache_hash_entry_id_t; +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Entry of LCache hash table + */ +typedef struct +{ + /** Pointer to a property of the object */ + ecma_property_t *prop_p; + + /** Entry identifier in LCache */ + ecma_lcache_hash_entry_id_t id; +} ecma_lcache_hash_entry_t; + +/** + * Number of rows in LCache's hash table + */ +#define ECMA_LCACHE_HASH_ROWS_COUNT 128 + +/** + * Number of entries in a row of LCache's hash table + */ +#define ECMA_LCACHE_HASH_ROW_LENGTH 2 + +#endif /* JERRY_LCACHE */ + +#if JERRY_BUILTIN_TYPEDARRAY + +/** + * Function callback descriptor of a %TypedArray% object getter + */ +typedef ecma_value_t (*ecma_typedarray_getter_fn_t) (lit_utf8_byte_t *src); + +/** + * Function callback descriptor of a %TypedArray% object setter + */ +typedef ecma_value_t (*ecma_typedarray_setter_fn_t) (lit_utf8_byte_t *src, ecma_value_t value); + +/** + * Builtin id for the different types of TypedArray's + */ +typedef enum +{ + ECMA_INT8_ARRAY, /**< Int8Array */ + ECMA_UINT8_ARRAY, /**< Uint8Array */ + ECMA_UINT8_CLAMPED_ARRAY, /**< Uint8ClampedArray */ + ECMA_INT16_ARRAY, /**< Int16Array */ + ECMA_UINT16_ARRAY, /**< Uint16Array */ + ECMA_INT32_ARRAY, /**< Int32Array */ + ECMA_UINT32_ARRAY, /**< Uint32Array */ + ECMA_FLOAT32_ARRAY, /**< Float32Array */ + ECMA_FLOAT64_ARRAY, /**< Float64Array */ + /* ECMA_TYPEDARRAY_IS_BIGINT_TYPE macro should be updated when new types are added */ + ECMA_BIGINT64_ARRAY, /**< BigInt64Array */ + ECMA_BIGUINT64_ARRAY, /**< BigUInt64Array */ +} ecma_typedarray_type_t; + +/** + * TypedArray flags. + */ +typedef enum +{ + ECMA_TYPEDARRAY_IS_EXTENDED = (1u << 0), /* an ecma_extended_typedarray_object_t is allocated for the TypedArray */ +} ecma_typedarray_flag_t; + +/** + * Array buffer flags. + */ +typedef enum +{ + ECMA_ARRAYBUFFER_HAS_POINTER = (1u << 0), /* ArrayBuffer has a buffer pointer. */ + ECMA_ARRAYBUFFER_ALLOCATED = (1u << 1), /* ArrayBuffer memory is allocated */ + ECMA_ARRAYBUFFER_DETACHED = (1u << 2), /* ArrayBuffer has been detached */ +} ecma_arraybuffer_flag_t; + +/** + * Structure for array buffers with a backing store pointer. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + void *buffer_p; /**< pointer to the backing store of the array buffer object */ + void *arraybuffer_user_p; /**< user pointer passed to the free callback */ +} ecma_arraybuffer_pointer_t; + +/** + * Some internal properties of TypedArray object. + * It is only used when the offset is not 0, and + * the array-length is not buffer-length / element_size. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + uint32_t byte_offset; /**< the byteoffset of the above arraybuffer */ + uint32_t array_length; /**< the array length */ +} ecma_extended_typedarray_object_t; + +/** + * General structure for query %TypedArray% object's properties. + **/ +typedef struct +{ + ecma_object_t *array_buffer_p; /**< pointer to the typedArray's [[ViewedArrayBuffer]] internal slot */ + ecma_typedarray_type_t id; /**< [[TypedArrayName]] internal slot */ + uint32_t length; /**< [[ByteLength]] internal slot */ + uint32_t offset; /**< [[ByteOffset]] internal slot. */ + uint8_t shift; /**< the element size shift in the typedArray */ + uint8_t element_size; /**< element size based on [[TypedArrayName]] in Table 49 */ +} ecma_typedarray_info_t; + +#if JERRY_BUILTIN_BIGINT +/** + * Checks whether a given typedarray is BigInt type or not. + **/ +#define ECMA_TYPEDARRAY_IS_BIGINT_TYPE(id) ((id) >= ECMA_BIGINT64_ARRAY) + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** + * Executable (e.g. generator, async) object flags. + */ +typedef enum +{ + ECMA_EXECUTABLE_OBJECT_COMPLETED = (1u << 0), /**< executable object is completed and cannot be resumed */ + ECMA_EXECUTABLE_OBJECT_RUNNING = (1u << 1), /**< executable object is currently running */ + /* Generator specific flags. */ + ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD = (1u << 2), /**< the executable object performs + * an await or a yield* operation */ + ECMA_ASYNC_GENERATOR_CALLED = (1u << 3), /**< the async generator was executed before */ + /* This must be the last generator specific flag. */ + ECMA_AWAIT_STATE_SHIFT = 4, /**< shift for await states */ +} ecma_executable_object_flags_t; + +/** + * Async function states after an await is completed. + */ +typedef enum +{ + ECMA_AWAIT_YIELD_NEXT, /**< wait for an iterator result object */ + ECMA_AWAIT_YIELD_NEXT_RETURN, /**< wait for an iterator result object after a return operation */ + ECMA_AWAIT_YIELD_RETURN, /**< wait for the argument passed to return operation */ + ECMA_AWAIT_YIELD_NEXT_VALUE, /**< wait for the value property of an iterator result object */ + ECMA_AWAIT_YIELD_OPERATION, /**< wait for the generator operation (next/throw/return) */ + ECMA_AWAIT_YIELD_CLOSE, /**< wait for the result of iterator close operation */ + /* After adding new ECMA_AWAIT_YIELD items, the ECMA_AWAIT_YIELD_END should be updated. */ + ECMA_AWAIT_FOR_CLOSE, /**< wait for a close iterator result object of for-await-of statement */ + ECMA_AWAIT_FOR_NEXT, /**< wait for an iterator result object of for-await-of statement */ +} ecma_await_states_t; + +/** + * Checks whether the executable object is waiting for resuming. + */ +#define ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED(executable_object_p) \ + (!((executable_object_p)->extended_object.u.cls.u2.executable_obj_flags \ + & (ECMA_EXECUTABLE_OBJECT_COMPLETED | ECMA_EXECUTABLE_OBJECT_RUNNING))) + +/** + * Last item of yield* related await states. + */ +#define ECMA_AWAIT_YIELD_END ECMA_AWAIT_YIELD_CLOSE + +/** + * Helper macro for ECMA_EXECUTABLE_OBJECT_RESUME_EXEC. + */ +#define ECMA_EXECUTABLE_OBJECT_RESUME_EXEC_MASK ((uint16_t) ~ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + +/** + * Resume execution of the byte code. + */ +#define ECMA_EXECUTABLE_OBJECT_RESUME_EXEC(executable_object_p) \ + ((executable_object_p)->extended_object.u.cls.u2.executable_obj_flags &= ECMA_EXECUTABLE_OBJECT_RESUME_EXEC_MASK) + +/** + * Enqueued task of an AsyncGenerator. + * + * An execution of a task has three steps: + * 1) Perform a next/throw/return operation + * 2) Resume the execution of the AsyncGenerator + * 3) Fulfill or reject a promise if the AsyncGenerator yielded a value + * (these Promises are created by the AsyncGenerator itself) + */ +typedef struct +{ + ecma_value_t next; /**< points to the next task which will be performed after this task is completed */ + ecma_value_t promise; /**< promise which will be fulfilled or rejected after this task is completed */ + ecma_value_t operation_value; /**< value argument of the operation */ + uint8_t operation_type; /**< type of operation (see ecma_async_generator_operation_type_t) */ +} ecma_async_generator_task_t; + +/** + * Definition of PromiseCapability Records + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header, and [[Promise]] internal slot */ + ecma_value_t resolve; /**< [[Resolve]] internal slot */ + ecma_value_t reject; /**< [[Reject]] internal slot */ +} ecma_promise_capabality_t; + +/** + * Definition of GetCapabilitiesExecutor Functions + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t capability; /**< [[Capability]] internal slot */ +} ecma_promise_capability_executor_t; + +/** + * Definition of Promise.all Resolve Element Functions + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t remaining_elements; /**< [[Remaining elements]] internal slot */ + ecma_value_t capability; /**< [[Capabilities]] internal slot */ + ecma_value_t values; /**< [[Values]] or [[Errors]] internal slot */ + uint32_t index; /**< [[Index]] and [[AlreadyCalled]] internal slot + * 0 - if the element has been resolved + * real index + 1 in the [[Values]] list - otherwise */ +} ecma_promise_all_executor_t; + +/** + * Promise prototype methods helper. + */ +typedef enum +{ + ECMA_PROMISE_ALL_RESOLVE, /**< promise.all resolve */ + ECMA_PROMISE_ALLSETTLED_RESOLVE, /**< promise.allSettled resolve */ + ECMA_PROMISE_ALLSETTLED_REJECT, /**< promise.allSettled reject */ + ECMA_PROMISE_ANY_REJECT, /**< promise.any reject */ +} ecma_promise_executor_type_t; + +#if JERRY_BUILTIN_DATAVIEW +/** + * Description of DataView objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + ecma_object_t *buffer_p; /**< [[ViewedArrayBuffer]] internal slot */ + uint32_t byte_offset; /**< [[ByteOffset]] internal slot */ +} ecma_dataview_object_t; +#endif /* JERRY_BUILTIN_DATAVIEW */ + +typedef enum +{ + ECMA_SYMBOL_FLAG_NONE = 0, /**< no options */ + ECMA_SYMBOL_FLAG_GLOBAL = (1 << 0), /**< symbol is a well known symbol, See also: 6.1.5.1 */ + ECMA_SYMBOL_FLAG_PRIVATE_KEY = (1 << 1), /**< symbol is a private field */ + ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD = (1 << 2), /**< symbol is a private method or accessor */ +} ecma_symbol_flags_t; + +/** + * Bitshift index for the symbol hash property + */ +#define ECMA_SYMBOL_FLAGS_SHIFT 3 + +/** + * Bitmask for symbol hash flags + */ +#define ECMA_SYMBOL_FLAGS_MASK ((1 << ECMA_SYMBOL_FLAGS_SHIFT) - 1) + +#if (JERRY_STACK_LIMIT != 0) +/** + * Check the current stack usage. If the limit is reached a RangeError is raised. + * The macro argument specifies the return value which is usally ECMA_VALUE_ERROR or NULL. + */ +#define ECMA_CHECK_STACK_USAGE_RETURN(RETURN_VALUE) \ + do \ + { \ + if (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT) \ + { \ + ecma_raise_maximum_callstack_error (); \ + return RETURN_VALUE; \ + } \ + } while (0) + +/** + * Specialized version of ECMA_CHECK_STACK_USAGE_RETURN which returns ECMA_VALUE_ERROR. + * This version should be used in most cases. + */ +#define ECMA_CHECK_STACK_USAGE() ECMA_CHECK_STACK_USAGE_RETURN (ECMA_VALUE_ERROR) +#else /* JERRY_STACK_LIMIT == 0) */ +/** + * If the stack limit is unlimited, this check is an empty macro. + */ +#define ECMA_CHECK_STACK_USAGE_RETURN(RETURN_VALUE) + +/** + * If the stack limit is unlimited, this check is an empty macro. + */ +#define ECMA_CHECK_STACK_USAGE() +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/** + * Invalid object pointer which represents abrupt completion + */ +#define ECMA_OBJECT_POINTER_ERROR ((ecma_object_t *) 0x01) + +/** + * Invalid property pointer which represents abrupt completion + */ +#define ECMA_PROPERTY_POINTER_ERROR ((ecma_property_t *) 0x01) + +#if JERRY_BUILTIN_PROXY + +/** + * Proxy object flags. + */ +typedef enum +{ + ECMA_PROXY_SKIP_RESULT_VALIDATION = (1u << 0), /**< skip result validation for [[GetPrototypeOf]], + * [[SetPrototypeOf]], [[IsExtensible]], + * [[PreventExtensions]], [[GetOwnProperty]], + * [[DefineOwnProperty]], [[HasProperty]], [[Get]], + * [[Set]], [[Delete]] and [[OwnPropertyKeys]] */ + ECMA_PROXY_IS_CALLABLE = (1u << 1), /**< proxy is callable */ + ECMA_PROXY_IS_CONSTRUCTABLE = (1u << 2), /**< proxy is constructable */ +} ecma_proxy_flag_types_t; + +/** + * Description of Proxy objects. + * + * A Proxy object's property list is used to store extra information: + * * The "header.u2.prototype_cp" 1st tag bit stores the IsCallable information. + * * The "header.u2.prototype_cp" 2nd tag bit stores the IsConstructor information. + */ +typedef struct +{ + ecma_object_t header; /**< header part */ + ecma_value_t target; /**< [[ProxyTarget]] internal slot */ + ecma_value_t handler; /**< [[ProxyHandler]] internal slot */ +} ecma_proxy_object_t; + +/** + * Description of Proxy objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + ecma_value_t proxy; /**< [[RevocableProxy]] internal slot */ +} ecma_revocable_proxy_object_t; +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * Type to repesent the maximum property index + * + * For ES6+ the maximum valid property index is 2**53 - 1 + */ +typedef uint64_t ecma_length_t; + +#if JERRY_BUILTIN_BIGINT + +/** + * BigUInt data is a sequence of uint32_t numbers. + */ +typedef uint32_t ecma_bigint_digit_t; + +/** + * Special BigInt value representing zero. + */ +#define ECMA_BIGINT_ZERO ((ecma_value_t) ECMA_TYPE_BIGINT) + +/** + * Special BigInt value representing zero when the result is pointer. + */ +#define ECMA_BIGINT_POINTER_TO_ZERO ((ecma_extended_primitive_t *) 0x1) + +/** + * Return the size of a BigInt value in ecma_bigint_data_t units. + */ +#define ECMA_BIGINT_GET_SIZE(value_p) \ + ((value_p)->u.bigint_sign_and_size & ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1)) + +/** + * Size of memory needs to be allocated for the digits of a BigInt. + * The value is rounded up for two digits. + */ +#define ECMA_BIGINT_GET_BYTE_SIZE(size) \ + (size_t) (((size) + sizeof (ecma_bigint_digit_t)) & ~(2 * sizeof (ecma_bigint_digit_t) - 1)) + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Struct for counting the different types properties in objects + */ +typedef struct +{ + uint32_t array_index_named_props; /**< number of array index named properties */ + uint32_t string_named_props; /**< number of string named properties */ + uint32_t symbol_named_props; /**< number of symbol named properties */ +} ecma_property_counter_t; + +/** + * Arguments object related status flags + */ +typedef enum +{ + ECMA_ARGUMENTS_OBJECT_NO_FLAGS = 0, /* unmapped arguments object */ + ECMA_ARGUMENTS_OBJECT_MAPPED = (1 << 0), /* mapped arguments object */ + ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE = (1 << 1), /* static mapped arguments object */ + ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED = (1 << 2), /* 'callee' property has been lazy initialized */ + ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 3), /* 'length' property has been lazy initialized */ + ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 4), /* 'Symbol.iterator' property has been lazy initialized */ +} ecma_arguments_object_flags_t; + +/** + * Definition of unmapped arguments object + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t callee; /**< 'callee' property */ +} ecma_unmapped_arguments_t; + +/** + * Definition of mapped arguments object + */ +typedef struct +{ + ecma_unmapped_arguments_t unmapped; /**< unmapped arguments object header */ + ecma_value_t lex_env; /**< environment reference */ + union + { + ecma_value_t byte_code; /**< callee's compiled code */ +#if JERRY_SNAPSHOT_EXEC + ecma_compiled_code_t *byte_code_p; /**< real byte code pointer */ +#endif /* JERRY_SNAPSHOT_EXEC */ + } u; +} ecma_mapped_arguments_t; + +/** + * Date object descriptor flags + */ +typedef enum +{ + ECMA_DATE_TZA_NONE = 0, /**< no time-zone adjustment is set */ + ECMA_DATE_TZA_SET = (1 << 0), /**< time-zone adjustment is set */ +} ecma_date_object_flags_t; + +/** + * Definition of date object + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_number_t date_value; /**< [[DateValue]] internal property */ +} ecma_date_object_t; + +/** + * Implicit class constructor flags + */ +typedef enum +{ + ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE = (1 << 0), /**< heritage object is present */ +} ecma_constructor_function_flags_t; + +/** + * Description of AsyncFromSyncIterator objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + ecma_value_t sync_next_method; /**< IteratorRecord [[NextMethod]] internal slot */ +} ecma_async_from_sync_iterator_object_t; + +/** + * Private method kind + */ +typedef enum +{ + ECMA_PRIVATE_FIELD = 0, /**< private field */ + ECMA_PRIVATE_METHOD, /**< private method */ + ECMA_PRIVATE_GETTER, /**< private setter */ + ECMA_PRIVATE_SETTER, /**< private getter */ +} ecma_private_property_kind_t; + +/** + * Private static property flag + */ +#define ECMA_PRIVATE_PROPERTY_STATIC_FLAG (1 << 2) + +/* + * Get private property kind from a descriptor + */ +#define ECMA_PRIVATE_PROPERTY_KIND(prop) ((ecma_private_property_kind_t) ((int) (prop) & (ECMA_PRIVATE_PROPERTY_STATIC_FLAG - 1))) + +/** + * @} + * @} + */ + +#endif /* !ECMA_GLOBALS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-collection.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-collection.cpp new file mode 100644 index 00000000..cd814324 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-collection.cpp @@ -0,0 +1,446 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-conversion.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Allocate a collection of ecma values. + * + * @return pointer to the collection + */ +ecma_collection_t * +ecma_new_collection (void) +{ + ecma_collection_t *collection_p; + collection_p = (ecma_collection_t *) jmem_heap_alloc_block (sizeof (ecma_collection_t)); + + collection_p->item_count = 0; + collection_p->capacity = ECMA_COLLECTION_INITIAL_CAPACITY; + const uint32_t size = ECMA_COLLECTION_ALLOCATED_SIZE (ECMA_COLLECTION_INITIAL_CAPACITY); + collection_p->buffer_p = (ecma_value_t *) jmem_heap_alloc_block (size); + + return collection_p; +} /* ecma_new_collection */ + +/** + * Deallocate a collection of ecma values without freeing it's values + * + * @return void + */ +void +ecma_collection_destroy (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + jmem_heap_free_block (collection_p->buffer_p, ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity)); + jmem_heap_free_block (collection_p, sizeof (ecma_collection_t)); +} /* ecma_collection_destroy */ + +/** + * Free the object collection elements and deallocate the collection + */ +void +ecma_collection_free_objects (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + if (ecma_is_value_object (buffer_p[i])) + { + ecma_deref_object (ecma_get_object_from_value (buffer_p[i])); + } + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free_objects */ + +/** + * Free the template literal objects and deallocate the collection + */ +void +ecma_collection_free_template_literal (ecma_collection_t *collection_p) /**< value collection */ +{ + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_object_t *object_p = ecma_get_object_from_value (collection_p->buffer_p[i]); + + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL); + array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_property_value_t *property_value_p; + + property_value_p = ecma_get_named_data_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_RAW)); + ecma_object_t *raw_object_p = ecma_get_object_from_value (property_value_p->value); + + JERRY_ASSERT (ecma_get_object_type (raw_object_p) == ECMA_OBJECT_TYPE_ARRAY); + + array_object_p = (ecma_extended_object_t *) raw_object_p; + + JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL); + array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_deref_object (raw_object_p); + ecma_deref_object (object_p); + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free_template_literal */ + +/** + * Free the non-object collection elements and deallocate the collection + */ +void +ecma_collection_free_if_not_object (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_free_value_if_not_object (buffer_p[i]); + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free_if_not_object */ + +/** + * Free the collection elements and deallocate the collection + */ +void +ecma_collection_free (ecma_collection_t *collection_p) /**< value collection */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_free_value (buffer_p[i]); + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free */ + +/** + * Append new value to ecma values collection + * + * Note: The reference count of the values are not increased + */ +void +ecma_collection_push_back (ecma_collection_t *collection_p, /**< value collection */ + ecma_value_t value) /**< ecma value to append */ +{ + JERRY_ASSERT (collection_p != NULL); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + if (JERRY_LIKELY (collection_p->item_count < collection_p->capacity)) + { + buffer_p[collection_p->item_count++] = value; + return; + } + + const uint32_t new_capacity = collection_p->capacity + ECMA_COLLECTION_GROW_FACTOR; + const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity); + const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity); + + buffer_p = (ecma_value_t *) jmem_heap_realloc_block (buffer_p, old_size, new_size); + buffer_p[collection_p->item_count++] = value; + collection_p->capacity = new_capacity; + + collection_p->buffer_p = buffer_p; +} /* ecma_collection_push_back */ + +/** + * Reserve space for the given amount of ecma_values in the collection + */ +void +ecma_collection_reserve (ecma_collection_t *collection_p, /**< value collection */ + uint32_t count) /**< number of ecma values to reserve */ +{ + JERRY_ASSERT (collection_p != NULL); + JERRY_ASSERT (UINT32_MAX - count > collection_p->capacity); + + const uint32_t new_capacity = collection_p->capacity + count; + const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity); + const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity); + + ecma_value_t *buffer_p = collection_p->buffer_p; + buffer_p = (ecma_value_t *) jmem_heap_realloc_block (buffer_p, old_size, new_size); + + collection_p->capacity = new_capacity; + collection_p->buffer_p = buffer_p; +} /* ecma_collection_reserve */ + +/** + * Append a list of values to the end of the collection + */ +void +ecma_collection_append (ecma_collection_t *collection_p, /**< value collection */ + const ecma_value_t *buffer_p, /**< values to append */ + uint32_t count) /**< number of ecma values to append */ +{ + JERRY_ASSERT (collection_p != NULL); + JERRY_ASSERT (collection_p->capacity >= collection_p->item_count); + + uint32_t free_count = collection_p->capacity - collection_p->item_count; + + if (free_count < count) + { + ecma_collection_reserve (collection_p, count - free_count); + } + + memcpy (collection_p->buffer_p + collection_p->item_count, buffer_p, count * sizeof (ecma_value_t)); + collection_p->item_count += count; +} /* ecma_collection_append */ + +/** + * Helper function to check if a given collection have duplicated properties or not + * + * @return true - if there are duplicated properties in the collection + * false - otherwise + */ +bool +ecma_collection_check_duplicated_entries (ecma_collection_t *collection_p) /**< prop name collection */ +{ + if (collection_p->item_count == 0) + { + return false; + } + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count - 1; i++) + { + ecma_string_t *current_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + for (uint32_t j = i + 1; j < collection_p->item_count; j++) + { + if (ecma_compare_ecma_strings (current_name_p, ecma_get_prop_name_from_value (buffer_p[j]))) + { + return true; + } + } + } + + return false; +} /* ecma_collection_check_duplicated_entries */ + +/** + * Check the string value existance in the collection. + * + * Used by: + * - ecma_builtin_json_stringify step 4.b.ii.5 + * - ecma_op_object_enumerate + * + * @return true, if the string is already in the collection. + */ +bool +ecma_collection_has_string_value (ecma_collection_t *collection_p, /**< collection */ + ecma_string_t *string_p) /**< string */ +{ + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_string_t *current_p = ecma_get_string_from_value (buffer_p[i]); + + if (ecma_compare_ecma_strings (current_p, string_p)) + { + return true; + } + } + + return false; +} /* ecma_collection_has_string_value */ + +/** + * Initial capacity of an ecma-collection + */ +#define ECMA_COMPACT_COLLECTION_GROWTH 8 + +/** + * Set the size of the compact collection + */ +#define ECMA_COMPACT_COLLECTION_SET_SIZE(compact_collection_p, item_count, unused_items) \ + ((compact_collection_p)[0] = (((item_count) << ECMA_COMPACT_COLLECTION_SIZE_SHIFT) | (unused_items))) + +/** + * Set the size of the compact collection + */ +#define ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT(compact_collection_p) \ + ((compact_collection_p)[0] & ((1 << ECMA_COMPACT_COLLECTION_SIZE_SHIFT) - 1)) + +/** + * Allocate a compact collection of ecma values + * + * @return pointer to the compact collection + */ +ecma_value_t * +ecma_new_compact_collection (void) +{ + size_t size = (ECMA_COMPACT_COLLECTION_GROWTH / 2) * sizeof (ecma_value_t); + ecma_value_t *compact_collection_p = (ecma_value_t *) jmem_heap_alloc_block (size); + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, + ECMA_COMPACT_COLLECTION_GROWTH / 2, + (ECMA_COMPACT_COLLECTION_GROWTH / 2) - 1); + return compact_collection_p; +} /* ecma_new_compact_collection */ + +/** + * Append a value to the compact collection + * + * @return updated pointer to the compact collection + */ +ecma_value_t * +ecma_compact_collection_push_back (ecma_value_t *compact_collection_p, /**< compact collection */ + ecma_value_t value) /**< ecma value to append */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + if (unused_items > 0) + { + compact_collection_p[size - unused_items] = value; + (*compact_collection_p)--; + return compact_collection_p; + } + + if (size == ECMA_COMPACT_COLLECTION_GROWTH / 2) + { + size_t old_size = (ECMA_COMPACT_COLLECTION_GROWTH / 2) * sizeof (ecma_value_t); + size_t new_size = ECMA_COMPACT_COLLECTION_GROWTH * sizeof (ecma_value_t); + compact_collection_p = (ecma_value_t *) jmem_heap_realloc_block (compact_collection_p, old_size, new_size); + + compact_collection_p[ECMA_COMPACT_COLLECTION_GROWTH / 2] = value; + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, + ECMA_COMPACT_COLLECTION_GROWTH, + (ECMA_COMPACT_COLLECTION_GROWTH / 2) - 1); + return compact_collection_p; + } + + size_t old_size = size * sizeof (ecma_value_t); + size_t new_size = old_size + (ECMA_COMPACT_COLLECTION_GROWTH * sizeof (ecma_value_t)); + + compact_collection_p = (ecma_value_t *) jmem_heap_realloc_block (compact_collection_p, old_size, new_size); + compact_collection_p[size] = value; + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, + size + ECMA_COMPACT_COLLECTION_GROWTH, + ECMA_COMPACT_COLLECTION_GROWTH - 1); + return compact_collection_p; +} /* ecma_compact_collection_push_back */ + +/** + * Discard the unused elements of a compact collection + * + * Note: + * further items should not be added after this call + * + * @return updated pointer to the compact collection + */ +ecma_value_t * +ecma_compact_collection_shrink (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + if (unused_items == 0) + { + return compact_collection_p; + } + + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + + size_t old_size = size * sizeof (ecma_value_t); + size_t new_size = (size - unused_items) * sizeof (ecma_value_t); + + compact_collection_p = (ecma_value_t *) jmem_heap_realloc_block (compact_collection_p, old_size, new_size); + + ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, size - unused_items, 0); + return compact_collection_p; +} /* ecma_compact_collection_shrink */ + +/** + * Free a compact collection + */ +void +ecma_compact_collection_free (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + ecma_value_t *end_p = compact_collection_p + size - unused_items; + ecma_value_t *current_p = compact_collection_p + 1; + + while (current_p < end_p) + { + ecma_free_value (*current_p++); + } + + jmem_heap_free_block (compact_collection_p, size * sizeof (ecma_value_t)); +} /* ecma_compact_collection_free */ + +/** + * Get the end of a compact collection + * + * @return pointer to the compact collection end + */ +ecma_value_t * +ecma_compact_collection_end (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p); + + return compact_collection_p + size - unused_items; +} /* ecma_compact_collection_end */ + +/** + * Destroy a compact collection + */ +void +ecma_compact_collection_destroy (ecma_value_t *compact_collection_p) /**< compact collection */ +{ + ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p); + + jmem_heap_free_block (compact_collection_p, size * sizeof (ecma_value_t)); +} /* ecma_compact_collection_destroy */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.cpp new file mode 100644 index 00000000..8ee7fb9f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.cpp @@ -0,0 +1,943 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" + +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +#if JERRY_NUMBER_TYPE_FLOAT64 + +/** + * \addtogroup ecmahelpersbigintegers Helpers for operations intermediate 128-bit integers + * @{ + */ + +/** + * 128-bit integer type + */ +typedef struct +{ + uint64_t hi; /**< high 64 bits */ + uint64_t lo; /**< low 64 bits */ +} ecma_uint128_t; + +/** + * Round high part of 128-bit integer to uint64_t + * + * @return rounded high to uint64_t + */ +static uint64_t +ecma_round_high_to_uint64 (ecma_uint128_t *num_p) +{ + uint64_t masked_lo = num_p->lo & ~(1ULL << 63u); + uint64_t masked_hi = num_p->hi & 0x1; + + if ((num_p->lo >> 63u != 0) && (masked_lo > 0 || masked_hi != 0)) + { + return (num_p->hi + 1); + } + + return num_p->hi; +} /* ecma_round_high_to_uint64 */ + +/** + * Left shift 128-bit integer by max 63 bits. + */ +static void +ecma_uint128_shift_left (ecma_uint128_t *num_p, int32_t shift) +{ + num_p->hi = (num_p->hi << shift) | (num_p->lo >> (64 - shift)); + num_p->lo <<= shift; +} /* ecma_uint128_shift_left */ + +/** + * Right shift 128-bit integer by max 63 bits. + */ +static void +ecma_uint128_shift_right (ecma_uint128_t *num_p, int32_t shift) +{ + num_p->lo = (num_p->lo >> shift) | (num_p->hi << (64 - shift)); + num_p->hi >>= shift; +} /* ecma_uint128_shift_right */ + +/** + * Add two 128-bit integer values and assign the result to the left one. + */ +static void +ecma_uint128_add (ecma_uint128_t *left_p, ecma_uint128_t *right_p) +{ + left_p->hi += right_p->hi; + left_p->lo += right_p->lo; + + if (left_p->lo < right_p->lo) + { + left_p->hi++; + } +} /* ecma_uint128_add */ + +/** + * Multiply 128-bit integer by 10 + */ +static void +ecma_uint128_mul10 (ecma_uint128_t *num_p) +{ + ecma_uint128_shift_left (num_p, 1u); + + ecma_uint128_t tmp = { num_p->hi, num_p->lo }; + ecma_uint128_shift_left (&tmp, 2u); + + ecma_uint128_add (num_p, &tmp); +} /* ecma_uint128_mul10 */ + +/** + * Divide 128-bit integer by 10 + * + * N = N3 *2^96 + N2 *2^64 + N1 *2^32 + N0 *2^0 // 128-bit dividend + * T = T3 *2^-32 + T2 *2^-64 + T1 *2^-96 + T0 *2^-128 // 128-bit divisor reciprocal, 1/10 * 2^-128 + * + * N * T = N3*T3 *2^64 + N2*T3 *2^32 + N1*T3 *2^0 + N0*T3 *2^-32 + * + N3*T2 *2^32 + N2*T2 *2^0 + N1*T2 *2^-32 + N0*T2 *2^-64 + * + N3*T1 *2^0 + N2*T1 *2^-32 + N1*T1 *2^-64 + N0*T1 *2^-96 + * + N3*T0 *2^-32 + N2*T0 *2^-64 + N1*T0 *2^-96 + N0*T0 *2^-128 + * + * Q3=carry Q2=^+carry Q1=^+carry Q0=^+carry fraction=^... + * + * Q = Q3 *2^96 + Q2 *2^64 + Q1 *2^32 + Q0 *2^0 // 128-bit quotient + */ +static void +ecma_uint128_div10 (ecma_uint128_t *num_p) +{ + /* estimation of reciprocal of 10, 128 bits right of the binary point (T1 == T2) */ + const uint64_t tenth_l = 0x9999999aul; + const uint64_t tenth_m = 0x99999999ul; + const uint64_t tenth_h = 0x19999999ul; + + const uint64_t l0 = ((uint32_t) num_p->lo) * tenth_l; + const uint64_t l1 = (num_p->lo >> 32u) * tenth_l; + const uint64_t l2 = ((uint32_t) num_p->hi) * tenth_l; + const uint64_t l3 = (num_p->hi >> 32u) * tenth_l; + const uint64_t m0 = ((uint32_t) num_p->lo) * tenth_m; + const uint64_t m1 = (num_p->lo >> 32u) * tenth_m; + const uint64_t m2 = ((uint32_t) num_p->hi) * tenth_m; + const uint64_t m3 = (num_p->hi >> 32u) * tenth_m; + const uint64_t h0 = ((uint32_t) num_p->lo) * tenth_h; + const uint64_t h1 = (num_p->lo >> 32u) * tenth_h; + const uint64_t h2 = ((uint32_t) num_p->hi) * tenth_h; + const uint64_t h3 = (num_p->hi >> 32u) * tenth_h; + + uint64_t q0 = l0 >> 32u; + q0 += (uint32_t) l1; + q0 += (uint32_t) m0; + + q0 >>= 32u; + q0 += l1 >> 32u; + q0 += m0 >> 32u; + q0 += (uint32_t) l2; + q0 += (uint32_t) m1; + q0 += (uint32_t) m0; + + q0 >>= 32u; + q0 += l2 >> 32u; + q0 += m1 >> 32u; + q0 += m0 >> 32u; + q0 += (uint32_t) l3; + q0 += (uint32_t) m2; + q0 += (uint32_t) m1; + q0 += (uint32_t) h0; + + q0 >>= 32u; + q0 += l3 >> 32u; + q0 += m2 >> 32u; + q0 += m1 >> 32u; + q0 += h0 >> 32u; + q0 += (uint32_t) m3; + q0 += (uint32_t) m2; + q0 += (uint32_t) h1; + + uint64_t q1 = q0 >> 32u; + q1 += m3 >> 32u; + q1 += m2 >> 32u; + q1 += h1 >> 32u; + q1 += (uint32_t) m3; + q1 += (uint32_t) h2; + + uint64_t q32 = q1 >> 32u; + q32 += m3 >> 32u; + q32 += h2 >> 32u; + q32 += h3; + + num_p->lo = (q1 << 32u) | ((uint32_t) q0); + num_p->hi = q32; +} /* ecma_uint128_div10 */ + +/** + * Count leading zeros in a 64-bit integer. The behaviour is undefined for 0. + * + * @return number of leading zeros. + */ +inline static int JERRY_ATTR_CONST +ecma_uint64_clz (uint64_t n) /**< integer to count leading zeros in */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_clzll (n); +#else /* !defined (__GNUC__) && !defined (__clang__) */ + JERRY_ASSERT (n != 0); + + int cnt = 0; + uint64_t one = 0x8000000000000000ull; + + while ((n & one) == 0) + { + cnt++; + one >>= 1; + } + + return cnt; +#endif /* !defined (__GNUC__) && !defined (__clang__) */ +} /* ecma_uint64_clz */ + +/** + * Count leading zeros in the top 4 bits of a 64-bit integer. + * + * @return number of leading zeros in top 4 bits. + */ +inline static int JERRY_ATTR_CONST +ecma_uint64_clz_top4 (uint64_t n) /**< integer to count leading zeros in */ +{ + static const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; + return ecma_uint4_clz[n >> 60]; +} /* ecma_uint64_clz */ + +/** + * Shift required to clear 4 bits of a 64-bit integer. + * + * @return 0-4 + */ +inline static int JERRY_ATTR_CONST +ecma_uint64_normalize_shift (uint64_t n) /**< integer to count leading zeros in */ +{ + static const uint8_t ecma_uint4_shift[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; + + return ecma_uint4_shift[n >> 60]; +} /* ecma_uint64_normalize_shift */ + +/** + * @} + */ + +/** + * Number.MAX_VALUE exponent part when using 64 bit float representation. + */ +#define NUMBER_MAX_DECIMAL_EXPONENT 308 +/** + * Number.MIN_VALUE exponent part when using 64 bit float representation. + */ +#define NUMBER_MIN_DECIMAL_EXPONENT -324 + +#elif !JERRY_NUMBER_TYPE_FLOAT64 + +/** + * Number.MAX_VALUE exponent part when using 32 bit float representation. + */ +#define NUMBER_MAX_DECIMAL_EXPONENT 38 +/** + * Number.MIN_VALUE exponent part when using 32 bit float representation. + */ +#define NUMBER_MIN_DECIMAL_EXPONENT -45 + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Value of epsilon + */ +#define EPSILON 0.0000001 + +/** + * ECMA-defined conversion from string to number for different radixes (2, 8, 16). + * + * See also: + * ECMA-262 v5 9.3.1 + * ECMA-262 v6 7.1.3.1 + * + * @return NaN - if the conversion fails + * converted number - otherwise + */ +ecma_number_t +ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, /**< utf-8 string */ + const lit_utf8_size_t string_size, /**< end of utf-8 string */ + uint32_t radix, /**< radix */ + uint32_t options) /**< option flags */ +{ + JERRY_ASSERT (radix == 2 || radix == 8 || radix == 16); + JERRY_ASSERT (*str_p == LIT_CHAR_0); + + const lit_utf8_byte_t *end_p = str_p + string_size; + + /* Skip leading zero */ + str_p++; + + if (radix != 8 || LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_O) + { + /* Skip radix specifier */ + str_p++; + } + + ecma_number_t num = ECMA_NUMBER_ZERO; + + while (str_p < end_p) + { + lit_utf8_byte_t digit = *str_p++; + + if (digit == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + continue; + } + + if (!lit_char_is_hex_digit (digit)) + { + return ecma_number_make_nan (); + } + + uint32_t value = lit_char_hex_to_int (digit); + + if (value >= radix) + { + return ecma_number_make_nan (); + } + + num = num * radix + value; + } + + return num; +} /* ecma_utf8_string_to_number_by_radix */ + +/** + * ECMA-defined conversion of string to Number. + * + * See also: + * ECMA-262 v5, 9.3.1 + * + * @return NaN - if the conversion fails + * converted number - otherwise + */ +ecma_number_t +ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */ + lit_utf8_size_t str_size, /**< string size */ + uint32_t options) /**< allowing underscore option bit */ +{ + ecma_string_trim_helper (&str_p, &str_size); + const lit_utf8_byte_t *end_p = str_p + str_size; + + if (str_size == 0) + { + return ECMA_NUMBER_ZERO; + } + + bool sign = false; + + if (str_p + 2 < end_p && str_p[0] == LIT_CHAR_0) + { + uint8_t radix = lit_char_to_radix (str_p[1]); + + if (radix != 10) + { + return ecma_utf8_string_to_number_by_radix (str_p, str_size, radix, options); + } + } + + if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + else if (*str_p == LIT_CHAR_MINUS) + { + sign = true; + str_p++; + } + + /* Check if string is equal to "Infinity". */ + const lit_utf8_byte_t *infinity_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL); + const lit_utf8_size_t infinity_length = lit_get_magic_string_size (LIT_MAGIC_STRING_INFINITY_UL); + + if ((lit_utf8_size_t) (end_p - str_p) == infinity_length && memcmp (infinity_str_p, str_p, infinity_length) == 0) + { + return ecma_number_make_infinity (sign); + } + + uint64_t significand = 0; + uint32_t digit_count = 0; + int32_t decimal_exponent = 0; + bool has_significand = false; + + /* Parsing integer part */ + while (str_p < end_p) + { + if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + str_p++; + continue; + } + + if (!lit_char_is_decimal_digit (*str_p)) + { + break; + } + + has_significand = true; + uint32_t digit_value = (uint32_t) (*str_p++ - LIT_CHAR_0); + + if (digit_count == 0 && digit_value == 0) + { + /* Leading zeros are omitted. */ + continue; + } + + if (digit_count >= ECMA_NUMBER_MAX_DIGITS) + { + decimal_exponent++; + continue; + } + + significand = significand * 10 + digit_value; + digit_count++; + } + + /* Parse fraction part */ + if (str_p < end_p && *str_p == LIT_CHAR_DOT) + { + str_p++; + + while (str_p < end_p) + { + if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + str_p++; + continue; + } + + if (!lit_char_is_decimal_digit (*str_p)) + { + break; + } + + has_significand = true; + uint32_t digit_value = (uint32_t) (*str_p++ - LIT_CHAR_0); + + if (digit_count == 0 && digit_value == 0) + { + /* Leading zeros are omitted. */ + decimal_exponent--; + continue; + } + + if (digit_count < ECMA_NUMBER_MAX_DIGITS) + { + significand = significand * 10 + digit_value; + digit_count++; + decimal_exponent--; + } + } + } + + /* Parsing exponent */ + if (str_p < end_p && LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_E) + { + str_p++; + + int32_t exponent = 0; + int32_t exponent_sign = 1; + + if (str_p >= end_p) + { + return ecma_number_make_nan (); + } + + if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + else if (*str_p == LIT_CHAR_MINUS) + { + exponent_sign = -1; + str_p++; + } + + if (str_p >= end_p || !lit_char_is_decimal_digit (*str_p)) + { + return ecma_number_make_nan (); + } + + while (str_p < end_p) + { + if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE)) + { + str_p++; + continue; + } + + if (!lit_char_is_decimal_digit (*str_p)) + { + break; + } + + int32_t digit_value = (*str_p++ - LIT_CHAR_0); + exponent = exponent * 10 + digit_value; + + if (exponent_sign * exponent > NUMBER_MAX_DECIMAL_EXPONENT) + { + return ecma_number_make_infinity (sign); + } + + if (exponent_sign * exponent < NUMBER_MIN_DECIMAL_EXPONENT) + { + return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO; + } + } + + decimal_exponent += exponent_sign * exponent; + } + + if (!has_significand || str_p < end_p) + { + return ecma_number_make_nan (); + } + + if (significand == 0) + { + return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO; + } + +#if JERRY_NUMBER_TYPE_FLOAT64 + /* + * 128-bit mantissa storage + * + * Normalized: |4 bits zero|124-bit mantissa with highest bit set to 1| + */ + ecma_uint128_t significand_uint128 = { significand, 0 }; + + /* Normalizing mantissa */ + int shift = 4 - ecma_uint64_clz (significand_uint128.hi); + + if (shift < 0) + { + ecma_uint128_shift_left (&significand_uint128, -shift); + } + else + { + ecma_uint128_shift_right (&significand_uint128, shift); + } + + int32_t binary_exponent = ECMA_NUMBER_FRACTION_WIDTH + shift; + + while (decimal_exponent > 0) + { + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) == 4); + + ecma_uint128_mul10 (&significand_uint128); + decimal_exponent--; + + /* Re-normalizing mantissa */ + shift = ecma_uint64_normalize_shift (significand_uint128.hi); + JERRY_ASSERT (shift >= 0 && shift <= 4); + + ecma_uint128_shift_right (&significand_uint128, shift); + binary_exponent += shift; + } + + while (decimal_exponent < 0) + { + /* Denormalizing mantissa, moving highest 1 to bit 127 */ + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) <= 4); + shift = ecma_uint64_clz_top4 (significand_uint128.hi); + JERRY_ASSERT (shift >= 0 && shift <= 4); + + ecma_uint128_shift_left (&significand_uint128, shift); + binary_exponent -= shift; + + ecma_uint128_div10 (&significand_uint128); + decimal_exponent++; + } + + /* + * Preparing mantissa for conversion to 52-bit representation, converting it to: + * + * |11 zero bits|1|116 mantissa bits| + */ + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) <= 4); + shift = 11 - ecma_uint64_clz_top4 (significand_uint128.hi); + ecma_uint128_shift_right (&significand_uint128, shift); + binary_exponent += shift; + + JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) == 11); + + binary_exponent += ECMA_NUMBER_EXPONENT_BIAS; + + /* Handle denormal numbers */ + if (binary_exponent < 1) + { + ecma_uint128_shift_right (&significand_uint128, -binary_exponent + 1); + binary_exponent = 0; + } + + significand = ecma_round_high_to_uint64 (&significand_uint128); + + if (significand >= 1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) + { + /* Rounding carried over to the most significant bit, re-normalize. + * No need to shift mantissa right, as the low 52 bits will be 0 regardless. */ + binary_exponent++; + } + + if (binary_exponent >= ((1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) + { + return ecma_number_make_infinity (sign); + } + + /* Mask low 52 bits. */ + significand &= ((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1); + + JERRY_ASSERT (binary_exponent < (1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1); + JERRY_ASSERT (significand < (1ull << ECMA_NUMBER_FRACTION_WIDTH)); + + return ecma_number_create (sign, (uint32_t) binary_exponent, significand); +#elif !JERRY_NUMBER_TYPE_FLOAT64 + /* Less precise conversion */ + ecma_number_t num = (ecma_number_t) (uint32_t) fraction_uint64; + + ecma_number_t m = e_sign ? (ecma_number_t) 0.1 : (ecma_number_t) 10.0; + + while (e) + { + if (e % 2) + { + num *= m; + } + + m *= m; + e /= 2; + } + + return num; +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +} /* ecma_utf8_string_to_number */ + +/** + * ECMA-defined conversion of UInt32 to String (zero-terminated). + * + * See also: + * ECMA-262 v5, 9.8.1 + * + * @return number of bytes copied to buffer + */ +lit_utf8_size_t +ecma_uint32_to_utf8_string (uint32_t value, /**< value to convert */ + lit_utf8_byte_t *out_buffer_p, /**< buffer for string */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + lit_utf8_byte_t *buf_p = out_buffer_p + buffer_size; + + do + { + JERRY_ASSERT (buf_p >= out_buffer_p); + + buf_p--; + *buf_p = (lit_utf8_byte_t) ((value % 10) + LIT_CHAR_0); + value /= 10; + } while (value != 0); + + JERRY_ASSERT (buf_p >= out_buffer_p); + + lit_utf8_size_t bytes_copied = (lit_utf8_size_t) (out_buffer_p + buffer_size - buf_p); + + if (JERRY_LIKELY (buf_p != out_buffer_p)) + { + memmove (out_buffer_p, buf_p, bytes_copied); + } + + return bytes_copied; +} /* ecma_uint32_to_utf8_string */ + +/** + * ECMA-defined conversion of Number value to UInt32 value + * + * See also: + * ECMA-262 v5, 9.6 + * + * @return 32-bit unsigned integer - result of conversion. + */ +uint32_t +ecma_number_to_uint32 (ecma_number_t num) /**< ecma-number */ +{ + if (JERRY_UNLIKELY (ecma_number_is_zero (num) || !ecma_number_is_finite (num))) + { + return 0; + } + + const bool sign = ecma_number_is_negative (num); + const ecma_number_t abs_num = sign ? -num : num; + + /* 2 ^ 32 */ + const uint64_t uint64_2_pow_32 = (1ull << 32); + + const ecma_number_t num_2_pow_32 = (float) uint64_2_pow_32; + + ecma_number_t num_in_uint32_range; + + if (abs_num >= num_2_pow_32) + { + num_in_uint32_range = ecma_number_remainder (abs_num, num_2_pow_32); + } + else + { + num_in_uint32_range = abs_num; + } + + /* Check that the floating point value can be represented with uint32_t. */ + JERRY_ASSERT (num_in_uint32_range < uint64_2_pow_32); + uint32_t uint32_num = (uint32_t) num_in_uint32_range; + + const uint32_t ret = sign ? (uint32_t)(-(int32_t)uint32_num) : uint32_num; + +#ifndef JERRY_NDEBUG + if (sign && uint32_num != 0) + { + JERRY_ASSERT (ret == uint64_2_pow_32 - uint32_num); + } + else + { + JERRY_ASSERT (ret == uint32_num); + } +#endif /* !JERRY_NDEBUG */ + + return ret; +} /* ecma_number_to_uint32 */ + +/** + * ECMA-defined conversion of Number value to Int32 value + * + * See also: + * ECMA-262 v5, 9.5 + * + * @return 32-bit signed integer - result of conversion. + */ +int32_t +ecma_number_to_int32 (ecma_number_t num) /**< ecma-number */ +{ + uint32_t uint32_num = ecma_number_to_uint32 (num); + + /* 2 ^ 32 */ + const int64_t int64_2_pow_32 = (1ll << 32); + + /* 2 ^ 31 */ + const uint32_t uint32_2_pow_31 = (1ull << 31); + + int32_t ret; + + if (uint32_num >= uint32_2_pow_31) + { + ret = (int32_t) (uint32_num - int64_2_pow_32); + } + else + { + ret = (int32_t) uint32_num; + } + +#ifndef JERRY_NDEBUG + int64_t int64_num = uint32_num; + + JERRY_ASSERT (int64_num >= 0); + + if (int64_num >= uint32_2_pow_31) + { + JERRY_ASSERT (ret == int64_num - int64_2_pow_32); + } + else + { + JERRY_ASSERT (ret == int64_num); + } +#endif /* !JERRY_NDEBUG */ + + return ret; +} /* ecma_number_to_int32 */ + +/** + * Perform conversion of ecma-number to decimal representation with decimal exponent. + * + * Note: + * The calculated values correspond to s, n, k parameters in ECMA-262 v5, 9.8.1, item 5: + * - parameter out_digits_p corresponds to s, the digits of the number; + * - parameter out_decimal_exp_p corresponds to n, the decimal exponent; + * - return value corresponds to k, the number of digits. + * + * @return the number of digits + */ +lit_utf8_size_t +ecma_number_to_decimal (ecma_number_t num, /**< ecma-number */ + lit_utf8_byte_t *out_digits_p, /**< [out] buffer to fill with digits */ + int32_t *out_decimal_exp_p) /**< [out] decimal exponent */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + JERRY_ASSERT (!ecma_number_is_zero (num)); + JERRY_ASSERT (!ecma_number_is_infinity (num)); + JERRY_ASSERT (!ecma_number_is_negative (num)); + + return ecma_errol0_dtoa ((double) num, out_digits_p, out_decimal_exp_p); +} /* ecma_number_to_decimal */ + +/** + * Convert ecma-number to zero-terminated string + * + * See also: + * ECMA-262 v5, 9.8.1 + * + * + * @return size of utf-8 string + */ +lit_utf8_size_t +ecma_number_to_utf8_string (ecma_number_t num, /**< ecma-number */ + lit_utf8_byte_t *buffer_p, /**< buffer for utf-8 string */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + lit_utf8_byte_t *dst_p; + + if (ecma_number_is_nan (num)) + { + /* 1. */ + dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_NAN, buffer_p, buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (ecma_number_is_zero (num)) + { + /* 2. */ + *buffer_p = LIT_CHAR_0; + JERRY_ASSERT (1 <= buffer_size); + return 1; + } + + dst_p = buffer_p; + + if (ecma_number_is_negative (num)) + { + /* 3. */ + *dst_p++ = LIT_CHAR_MINUS; + num = -num; + } + + if (ecma_number_is_infinity (num)) + { + /* 4. */ + dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_INFINITY_UL, + dst_p, + (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + /* 5. */ + uint32_t num_uint32 = ecma_number_to_uint32 (num); + + if (((ecma_number_t) num_uint32) == num) + { + dst_p += ecma_uint32_to_utf8_string (num_uint32, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + /* decimal exponent */ + int32_t n; + /* number of digits in mantissa */ + int32_t k; + + k = (int32_t) ecma_number_to_decimal (num, dst_p, &n); + + if (k <= n && n <= 21) + { + /* 6. */ + dst_p += k; + + memset (dst_p, LIT_CHAR_0, (size_t) (n - k)); + dst_p += n - k; + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (0 < n && n <= 21) + { + /* 7. */ + memmove (dst_p + n + 1, dst_p + n, (size_t) (k - n)); + *(dst_p + n) = LIT_CHAR_DOT; + dst_p += k + 1; + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (-6 < n && n <= 0) + { + /* 8. */ + memmove (dst_p + 2 - n, dst_p, (size_t) k); + memset (dst_p + 2, LIT_CHAR_0, (size_t) -n); + *dst_p = LIT_CHAR_0; + *(dst_p + 1) = LIT_CHAR_DOT; + dst_p += k - n + 2; + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + return (lit_utf8_size_t) (dst_p - buffer_p); + } + + if (k == 1) + { + /* 9. */ + dst_p++; + } + else + { + /* 10. */ + memmove (dst_p + 2, dst_p + 1, (size_t) (k - 1)); + *(dst_p + 1) = LIT_CHAR_DOT; + dst_p += k + 1; + } + + /* 9., 10. */ + *dst_p++ = LIT_CHAR_LOWERCASE_E; + *dst_p++ = (n >= 1) ? LIT_CHAR_PLUS : LIT_CHAR_MINUS; + uint32_t t = (uint32_t) (n >= 1 ? (n - 1) : -(n - 1)); + + dst_p += ecma_uint32_to_utf8_string (t, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); + + JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + + return (lit_utf8_size_t) (dst_p - buffer_p); +} /* ecma_number_to_utf8_string */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.cpp new file mode 100644 index 00000000..07932429 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.cpp @@ -0,0 +1,245 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is based on work under the following copyright and permission + * notice: + * + * Copyright (c) 2016 Marc Andrysco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Printing Floating-Point Numbers + * + * available at http://cseweb.ucsd.edu/~mandrysc/pub/dtoa.pdf + */ + +/** + * Floating point format definitions (next float value) + */ +#define ECMA_NEXT_FLOAT(value) (nextafter ((value), INFINITY)) +/** + * Floating point format definitions (previous float value) + */ +#define ECMA_PREV_FLOAT(value) (nextafter ((value), -INFINITY)) + +/** + * Value of epsilon + */ +#define ERROL0_EPSILON 0.0000001 + +/** + * High-precision data structure. + */ +typedef struct +{ + double value; /**< value */ + double offset; /**< offset */ +} ecma_high_prec_t; + +/** + * Normalize the number by factoring in the error. + * + * @return void + */ +static inline void +ecma_normalize_high_prec_data (ecma_high_prec_t *hp_data_p) /**< [in, out] float pair */ +{ + double val = hp_data_p->value; + + hp_data_p->value += hp_data_p->offset; + hp_data_p->offset += val - hp_data_p->value; +} /* ecma_normalize_high_prec_data */ + +/** + * Multiply the high-precision number by ten. + * + * @return void + */ +static inline void +ecma_multiply_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */ +{ + double value = hp_data_p->value; + + hp_data_p->value *= 10.0; + hp_data_p->offset *= 10.0; + + double offset = hp_data_p->value; + + offset -= value * 8.0; + offset -= value * 2.0; + + hp_data_p->offset -= offset; + + ecma_normalize_high_prec_data (hp_data_p); +} /* ecma_multiply_high_prec_by_10 */ + +/** + * Divide the high-precision number by ten. + */ +static void +ecma_divide_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */ +{ + double value = hp_data_p->value; + + hp_data_p->value /= 10.0; + hp_data_p->offset /= 10.0; + + value -= hp_data_p->value * 8.0; + value -= hp_data_p->value * 2.0; + + hp_data_p->offset += value / 10.0; + + ecma_normalize_high_prec_data (hp_data_p); +} /* ecma_divide_high_prec_by_10 */ + +/** + * Errol0 double to ASCII conversion, guaranteed correct but possibly not optimal. + * + * @return number of generated digits + */ +lit_utf8_size_t +ecma_errol0_dtoa (double val, /**< ecma number */ + lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */ + int32_t *exp_p) /**< [out] exponent */ +{ + double power_of_10 = 1.0; + int32_t exponent = 1; + + /* normalize the midpoint */ + ecma_high_prec_t mid; + + mid.value = val; + mid.offset = 0.0; + + while (((mid.value > 10.0) || ((mid.value == 10.0) && (mid.offset >= 0.0))) && (exponent < 308)) + { + exponent++; + ecma_divide_high_prec_by_10 (&mid); + power_of_10 /= 10.0; + } + + while (((mid.value < 1.0) || ((mid.value == 1.0) && (mid.offset < 0.0))) && (exponent > -307)) + { + exponent--; + ecma_multiply_high_prec_by_10 (&mid); + power_of_10 *= 10.0; + } + + ecma_high_prec_t high_bound, low_bound; + + high_bound.value = mid.value; + high_bound.offset = mid.offset; + + if (ECMA_NEXT_FLOAT (val) != INFINITY) + { + high_bound.offset += (ECMA_NEXT_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); + } + + low_bound.value = mid.value; + low_bound.offset = mid.offset + (ECMA_PREV_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); + + ecma_normalize_high_prec_data (&high_bound); + ecma_normalize_high_prec_data (&low_bound); + + /* normalized boundaries */ + + while (high_bound.value > 10.0 || (high_bound.value == 10.0 && (high_bound.offset >= 0.0))) + { + exponent++; + ecma_divide_high_prec_by_10 (&high_bound); + ecma_divide_high_prec_by_10 (&low_bound); + } + + while (high_bound.value < 1.0 || (high_bound.value == 1.0 && (high_bound.offset < 0.0))) + { + exponent--; + ecma_multiply_high_prec_by_10 (&high_bound); + ecma_multiply_high_prec_by_10 (&low_bound); + } + + /* digit generation */ + + lit_utf8_byte_t *dst_p = buffer_p; + + while (high_bound.value != 0.0 || high_bound.offset != 0.0) + { + uint8_t high_digit = (uint8_t) high_bound.value; + + if ((high_bound.value == high_digit) && (high_bound.offset < 0)) + { + high_digit = (uint8_t) (high_digit - 1u); + } + + uint8_t low_digit = (uint8_t) low_bound.value; + + if ((low_bound.value == low_digit) && (low_bound.offset < 0)) + { + low_digit = (uint8_t) (low_digit - 1u); + } + + if (low_digit != high_digit) + { + break; + } + + *dst_p++ = (lit_utf8_byte_t) ('0' + high_digit); + + high_bound.value -= high_digit; + ecma_multiply_high_prec_by_10 (&high_bound); + + low_bound.value -= low_digit; + ecma_multiply_high_prec_by_10 (&low_bound); + } + + double mdig = (high_bound.value + low_bound.value) / 2.0 + 0.5; + *dst_p++ = (lit_utf8_byte_t) ('0' + (uint8_t) mdig); + + *exp_p = exponent; + + return (lit_utf8_size_t) (dst_p - buffer_p); +} /* ecma_errol0_dtoa */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp new file mode 100644 index 00000000..66d542a0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp @@ -0,0 +1,334 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Create a native pointer property to store the native pointer and its type info. + * + * @return true - if property was just created with specified value, + * false - otherwise, if property existed before the call, it's value was updated + */ +bool +ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create property in */ + void *native_p, /**< native pointer */ + const jerry_object_native_info_t *native_info_p) /**< native type info */ +{ + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); + + if (native_info_p != NULL && native_info_p->number_of_references > 0) + { + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + bool is_new = (property_p == NULL); + + ecma_native_pointer_t *native_pointer_p; + + if (property_p == NULL) + { + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + + ecma_property_value_t *value_p; + ECMA_CREATE_INTERNAL_PROPERTY (obj_p, name_p, property_p, value_p); + + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + } + else if (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL) + { + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + + if (native_pointer_p->native_info_p == native_info_p) + { + native_pointer_p->native_p = native_p; + return false; + } + + value_p->value = JMEM_CP_NULL; + (void) value_p->value; /* Make cppcheck happy. */ + *property_p &= (ecma_property_t) ~ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + + ecma_native_pointer_chain_t *item_p; + item_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->data = *native_pointer_p; + + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + + item_p->next_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->next_p->next_p = NULL; + + native_pointer_p = &item_p->next_p->data; + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, item_p); + } + else + { + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (value_p->value == JMEM_CP_NULL) + { + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + } + else + { + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (item_p != NULL && item_p->next_p != NULL); + + while (true) + { + if (item_p->data.native_info_p == native_info_p) + { + /* The native info already exists -> update the corresponding data */ + item_p->data.native_p = native_p; + return false; + } + + if (item_p->next_p == NULL) + { + /* The native info does not exist -> append a new element to the chain */ + break; + } + + item_p = item_p->next_p; + } + + ecma_native_pointer_chain_t *new_item_p; + + new_item_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->next_p = new_item_p; + new_item_p->next_p = NULL; + + native_pointer_p = &new_item_p->data; + } + } + + native_pointer_p->native_p = native_p; + native_pointer_p->native_info_p = (jerry_object_native_info_t *) native_info_p; + + return is_new; +} /* ecma_create_native_pointer_property */ + +/** + * Get value of native package stored in the object's property with specified identifier + * + * Note: + * property identifier should be one of the following: + * - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER + * + * @return native pointer data if property exists + * NULL otherwise + */ +ecma_native_pointer_t * +ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */ + const jerry_object_native_info_t *native_info_p) /**< native type info */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + /* Fast access mode array can not have native pointer properties */ + return NULL; + } + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); + + if (native_info_p != NULL && native_info_p->number_of_references > 0) + { + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + if (property_p == NULL) + { + return NULL; + } + + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_LIKELY (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + + if (native_pointer_p->native_info_p == native_info_p) + { + return native_pointer_p; + } + + return NULL; + } + + if (value_p->value == JMEM_CP_NULL) + { + return NULL; + } + + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (item_p != NULL && item_p->next_p != NULL); + + do + { + if (item_p->data.native_info_p == native_info_p) + { + return &item_p->data; + } + + item_p = item_p->next_p; + } while (item_p != NULL); + + return NULL; +} /* ecma_get_native_pointer_value */ + +/** + * Delete the previously set native pointer by the native type info from the specified object. + * + * Note: + * If the specified object has no matching native pointer for the given native type info + * the function has no effect. + * + * @return true - if the native pointer has been deleted succesfully + * false - otherwise + */ +bool +ecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete property from */ + const jerry_object_native_info_t *native_info_p) /**< native type info */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + /* Fast access mode array can not have native pointer properties */ + return false; + } + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); + + if (native_info_p != NULL && native_info_p->number_of_references > 0) + { + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES); + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + if (property_p == NULL) + { + return false; + } + + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_LIKELY (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + + if (native_pointer_p->native_info_p != native_info_p) + { + return false; + } + + value_p->value = JMEM_CP_NULL; + *property_p &= (ecma_property_t) ~ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + return true; + } + + if (value_p->value == JMEM_CP_NULL) + { + return false; + } + + ecma_native_pointer_chain_t *first_p; + first_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (first_p != NULL && first_p->next_p != NULL); + + ecma_native_pointer_chain_t *item_p = first_p; + ecma_native_pointer_chain_t *prev_p = NULL; + + do + { + if (item_p->data.native_info_p == native_info_p) + { + if (prev_p == NULL) + { + /* The first element is deleted from the chain: change the property value. */ + first_p = item_p->next_p; + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, first_p); + } + else + { + /* A non-first element is deleted from the chain: update the previous pointer. */ + prev_p->next_p = item_p->next_p; + } + + jmem_heap_free_block (item_p, sizeof (ecma_native_pointer_chain_t)); + + if (first_p->next_p != NULL) + { + return true; + } + + /* Only one item remained. The ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL flag is + * set early to avoid using the chain if the allocation below triggers a GC. */ + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + + ecma_native_pointer_t *native_pointer_p; + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + *native_pointer_p = first_p->data; + + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + + jmem_heap_free_block (first_p, sizeof (ecma_native_pointer_chain_t)); + return true; + } + + prev_p = item_p; + item_p = item_p->next_p; + } while (item_p != NULL); + + return false; +} /* ecma_delete_native_pointer_property */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.cpp new file mode 100644 index 00000000..cde5524d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.cpp @@ -0,0 +1,677 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers-number.h" + +#include + +#include "ecma-conversion.h" + +#include "lit-char-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +JERRY_STATIC_ASSERT ((sizeof (ecma_value_t) == sizeof (ecma_integer_value_t)), + size_of_ecma_value_t_must_be_equal_to_the_size_of_ecma_integer_value_t); + +JERRY_STATIC_ASSERT ((((int)ECMA_DIRECT_SHIFT) == (((int)ECMA_VALUE_SHIFT) + 1)), currently_directly_encoded_values_has_one_extra_flag); + +JERRY_STATIC_ASSERT ((((1 << (ECMA_DIRECT_SHIFT - 1)) | ECMA_TYPE_DIRECT) == ECMA_DIRECT_TYPE_SIMPLE_VALUE), + currently_directly_encoded_values_start_after_direct_type_simple_value); + +JERRY_STATIC_ASSERT ((sizeof (ecma_number_t) == sizeof (ecma_binary_num_t)), + size_of_ecma_number_t_must_be_equal_to_binary_representation); + +/** + * Convert an ecma-number to it's binary representation. + * + * @return binary representation + */ +ecma_binary_num_t JERRY_ATTR_CONST +ecma_number_to_binary (ecma_number_t number) /**< ecma number */ +{ + ecma_number_accessor_t f; + f.as_number = number; + + return f.as_binary; +} /* ecma_number_to_binary */ + +/** + * Convert a binary representation to the corresponding ecma-number. + * + * @return ecma-number + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_from_binary (ecma_binary_num_t binary) /**< binary representation */ +{ + ecma_number_accessor_t f; + f.as_binary = binary; + + return f.as_number; +} /* ecma_number_from_binary */ + +/** + * Check signedness of the binary number. + * + * @return true - if sign bit is set + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_sign (ecma_binary_num_t binary) /**< binary representation */ +{ + return (binary & ECMA_NUMBER_SIGN_BIT) != 0; +} /* ecma_number_sign */ + +/** + * Get biased exponent field of the binary number. + * + * @return unsigned integer value of the biased exponent field + */ +uint32_t JERRY_ATTR_CONST +ecma_number_biased_exp (ecma_binary_num_t binary) /**< binary representation */ +{ + return (uint32_t) ((binary & ~ECMA_NUMBER_SIGN_BIT) >> ECMA_NUMBER_FRACTION_WIDTH); +} /* ecma_number_biased_exp */ + +/** + * Get fraction field of the binary number. + * + * @return unsigned integer value of the fraction field + */ +uint64_t JERRY_ATTR_CONST +ecma_number_fraction (ecma_binary_num_t binary) /**< binary representation */ +{ + return binary & ((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1); +} /* ecma_number_fraction */ + +/** + * Packing sign, fraction and biased exponent to ecma-number + * + * @return ecma-number with specified sign, biased_exponent and fraction + */ +ecma_number_t +ecma_number_create (bool sign, /**< sign */ + uint32_t biased_exp, /**< biased exponent */ + uint64_t fraction) /**< fraction */ +{ + JERRY_ASSERT ((biased_exp & ~((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) == 0); + JERRY_ASSERT ((fraction & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0); + + ecma_binary_num_t binary = biased_exp; + binary <<= ECMA_NUMBER_FRACTION_WIDTH; + + binary |= fraction; + + if (sign) + { + binary |= ECMA_NUMBER_SIGN_BIT; + } + + return ecma_number_from_binary (binary); +} /* ecma_number_create */ + +/** + * Check if ecma-number is NaN + * + * @return true - if biased exponent is filled with 1 bits and + fraction is filled with anything but not all zero bits, + * false - otherwise + */ +bool +ecma_number_is_nan (ecma_number_t num) /**< ecma-number */ +{ + bool is_nan = (num != num); + +#ifndef JERRY_NDEBUG + /* IEEE-754 2008, 3.4, a */ + ecma_binary_num_t binary = ecma_number_to_binary (num); + bool is_nan_exponent = (ecma_number_biased_exp (binary) == (1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1); + bool is_nan_fraction = (ecma_number_fraction (binary) > 0); + + bool is_nan_ieee754 = is_nan_exponent && is_nan_fraction; + JERRY_ASSERT (is_nan == is_nan_ieee754); +#endif /* !JERRY_NDEBUG */ + + return is_nan; +} /* ecma_number_is_nan */ + +/** + * Make a NaN. + * + * @return NaN value + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_make_nan (void) +{ + ecma_number_accessor_t f; + f.as_binary = ECMA_NUMBER_BINARY_QNAN; + + return f.as_number; +} /* ecma_number_make_nan */ + +/** + * Make an Infinity. + * + * @return if !sign - +Infinity value, + * else - -Infinity value. + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_make_infinity (bool sign) /**< sign of the value */ +{ + ecma_number_accessor_t f; + f.as_binary = ECMA_NUMBER_BINARY_INF; + + if (sign) + { + f.as_binary |= ECMA_NUMBER_SIGN_BIT; + } + + return f.as_number; +} /* ecma_number_make_infinity */ + +/** + * Check if ecma-number is negative + * + * @return true - if sign bit of ecma-number is set + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_is_negative (ecma_number_t num) /**< ecma-number */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + + return (ecma_number_to_binary (num) & ECMA_NUMBER_SIGN_BIT) != 0; +} /* ecma_number_is_negative */ + +/** + * Check if ecma-number is zero + * + * @return true - if fraction is zero and biased exponent is zero, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_is_zero (ecma_number_t num) /**< ecma-number */ +{ + bool is_zero = (num == ECMA_NUMBER_ZERO); + +#ifndef JERRY_NDEBUG + bool is_zero_ieee754 = ((ecma_number_to_binary (num) & ~ECMA_NUMBER_SIGN_BIT) == 0); + JERRY_ASSERT (is_zero == is_zero_ieee754); +#endif /* !JERRY_NDEBUG */ + + return is_zero; +} /* ecma_number_is_zero */ + +/** + * Check if number is infinity + * + * @return true - if biased exponent is filled with 1 bits and + * fraction is filled with zero bits, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_number_is_infinity (ecma_number_t num) /**< ecma-number */ +{ + return (ecma_number_to_binary (num) & ~ECMA_NUMBER_SIGN_BIT) == ECMA_NUMBER_BINARY_INF; +} /* ecma_number_is_infinity */ + +/** + * Check if number is finite + * + * @return true - if number is finite + * false - if number is NaN or infinity + */ +bool JERRY_ATTR_CONST +ecma_number_is_finite (ecma_number_t num) /**< ecma-number */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_isfinite (num); +#elif defined(_WIN32) + return isfinite (num); +#else /* !(defined(__GNUC__) || defined(__clang__) || defined(_WIN32)) */ + return !ecma_number_is_nan (num) && !ecma_number_is_infinity (num); +#endif /* defined (__GNUC__) || defined (__clang__) */ +} /* ecma_number_is_finite */ + +/** + * Get previous representable ecma-number + * + * @return maximum ecma-number that is less compared to passed argument + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_get_prev (ecma_number_t num) /**< ecma-number */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_nextafter (num, -INFINITY); +#else /* !defined (__GNUC__) && !defined (__clang__) */ + JERRY_ASSERT (!ecma_number_is_nan (num)); + ecma_binary_num_t binary = ecma_number_to_binary (num); + + /* If -Infinity, return self */ + if (binary == (ECMA_NUMBER_SIGN_BIT | ECMA_NUMBER_BINARY_INF)) + { + return num; + } + + /* If +0.0, return -0.0 */ + if (binary == ECMA_NUMBER_BINARY_ZERO) + { + return -num; + } + + if (ecma_number_sign (binary)) + { + return ecma_number_from_binary (binary + 1); + } + + return ecma_number_from_binary (binary - 1); +#endif /* !defined (__GNUC__) && !defined (__clang__) */ +} /* ecma_number_get_prev */ + +/** + * Get next representable ecma-number + * + * @return minimum ecma-number that is greater compared to passed argument + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_get_next (ecma_number_t num) /**< ecma-number */ +{ +#if defined(__GNUC__) || defined(__clang__) + return __builtin_nextafter (num, INFINITY); +#else /* !defined (__GNUC__) && !defined (__clang__) */ + JERRY_ASSERT (!ecma_number_is_nan (num)); + ecma_binary_num_t binary = ecma_number_to_binary (num); + + /* If +Infinity, return self */ + if (binary == ECMA_NUMBER_BINARY_INF) + { + return num; + } + + /* If -0.0, return +0.0 */ + if (binary == (ECMA_NUMBER_SIGN_BIT | ECMA_NUMBER_BINARY_ZERO)) + { + return -num; + } + + if (ecma_number_sign (binary)) + { + return ecma_number_from_binary (binary - 1); + } + + return ecma_number_from_binary (binary + 1); +#endif /* !defined (__GNUC__) && !defined (__clang__) */ +} /* ecma_number_get_next */ + +/** + * Truncate fractional part of the number + * + * @return integer part of the number + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_trunc (ecma_number_t num) /**< ecma-number */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + + ecma_binary_num_t binary = ecma_number_to_binary (num); + uint32_t exponent = ecma_number_biased_exp (binary); + + if (exponent < ECMA_NUMBER_EXPONENT_BIAS) + { + return ECMA_NUMBER_ZERO; + } + + uint32_t unbiased_exp = exponent - ECMA_NUMBER_EXPONENT_BIAS; + + if (unbiased_exp >= ECMA_NUMBER_FRACTION_WIDTH) + { + return num; + } + + binary &= ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH - unbiased_exp)) - 1); + return ecma_number_from_binary (binary); +} /* ecma_number_trunc */ + +/** + * Calculate remainder of division of two numbers, + * as specified in ECMA-262 v5, 11.5.3, item 6. + * + * Note: + * operands shouldn't contain NaN, Infinity, or zero. + * + * @return number - calculated remainder. + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_remainder (ecma_number_t left_num, /**< left operand */ + ecma_number_t right_num) /**< right operand */ +{ + JERRY_ASSERT (ecma_number_is_finite (left_num) && !ecma_number_is_zero (left_num)); + JERRY_ASSERT (ecma_number_is_finite (right_num) && !ecma_number_is_zero (right_num)); + + const ecma_number_t q = ecma_number_trunc (left_num / right_num); + ecma_number_t r = left_num - right_num * q; + + if (ecma_number_is_zero (r) && ecma_number_is_negative (left_num)) + { + r = -r; + } + + return r; +} /* ecma_number_remainder */ + +/** + * Compute power operation according to the ES standard. + * + * @return x ** y + */ +ecma_number_t JERRY_ATTR_CONST +ecma_number_pow (ecma_number_t x, /**< left operand */ + ecma_number_t y) /**< right operand */ +{ + if (ecma_number_is_nan (y) || (ecma_number_is_infinity (y) && (x == ECMA_NUMBER_ONE || x == ECMA_NUMBER_MINUS_ONE))) + { + /* Handle differences between ES5.1 and ISO C standards for pow. */ + return ecma_number_make_nan (); + } + + if (ecma_number_is_zero (y)) + { + /* Handle differences between ES5.1 and ISO C standards for pow. */ + return ECMA_NUMBER_ONE; + } + + return DOUBLE_TO_ECMA_NUMBER_T (pow (x, y)); +} /* ecma_number_pow */ + +/** + * ECMA-integer number multiplication. + * + * @return number - result of multiplication. + */ +ecma_value_t JERRY_ATTR_CONST +ecma_integer_multiply (ecma_integer_value_t left_integer, /**< left operand */ + ecma_integer_value_t right_integer) /**< right operand */ +{ +#if defined(__GNUC__) || defined(__clang__) + /* Check if either integer is power of 2 */ + if (JERRY_UNLIKELY ((left_integer & (left_integer - 1)) == 0)) + { + /* Right shift right_integer with log2 (left_integer) */ + return ecma_make_integer_value ( + (int32_t) ((uint32_t) right_integer << (__builtin_ctz ((unsigned int) left_integer)))); + } + + if (JERRY_UNLIKELY ((right_integer & (right_integer - 1)) == 0)) + { + /* Right shift left_integer with log2 (right_integer) */ + return ecma_make_integer_value ( + (int32_t) ((uint32_t) left_integer << (__builtin_ctz ((unsigned int) right_integer)))); + } +#endif /* defined (__GNUC__) || defined (__clang__) */ + + return ecma_make_integer_value (left_integer * right_integer); +} /* ecma_integer_multiply */ + +/** + * The Number object's 'parseInt' routine + * + * See also: + * ECMA-262 v5, 15.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_number_parse_int (const lit_utf8_byte_t *str_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t str_size, /**< routine's first argument's + * string buffer's size */ + ecma_value_t radix_value) /**< routine's second argument */ +{ + /* 2. Remove leading whitespace. */ + ecma_string_trim_helper (&str_p, &str_size); + + if (str_size == 0) + { + return ecma_make_nan_value (); + } + + const lit_utf8_byte_t *str_end_p = str_p + str_size; + + /* 3. */ + bool sign = false; + + /* 4. */ + if (*str_p == LIT_CHAR_MINUS) + { + sign = true; + str_p++; + } + /* 5. */ + else if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + + /* 6. */ + ecma_number_t radix_num; + radix_value = ecma_op_to_number (radix_value, &radix_num); + + if (ECMA_IS_VALUE_ERROR (radix_value)) + { + return ECMA_VALUE_ERROR; + } + + int32_t radix = ecma_number_to_int32 (radix_num); + + /* 7.*/ + bool strip_prefix = true; + + /* 8. */ + if (radix != 0) + { + /* 8.a */ + if (radix < 2 || radix > 36) + { + return ecma_make_nan_value (); + } + /* 8.b */ + else if (radix != 16) + { + strip_prefix = false; + } + } + /* 9. */ + else + { + radix = 10; + } + + /* 10. */ + if (strip_prefix && ((str_end_p - str_p) >= 2) && (str_p[0] == LIT_CHAR_0) + && (LEXER_TO_ASCII_LOWERCASE (str_p[1]) == LIT_CHAR_LOWERCASE_X)) + { + str_p += 2; + radix = 16; + } + + ecma_number_t value = ECMA_NUMBER_ZERO; + const lit_utf8_byte_t *digit_start_p = str_p; + + /* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */ + while (str_p < str_end_p) + { + ecma_char_t ch = *str_p; + + int32_t digit = 0; + + if (lit_char_is_decimal_digit (ch)) + { + digit = ch - LIT_CHAR_0; + } + else if (LEXER_TO_ASCII_LOWERCASE (ch) >= LIT_CHAR_LOWERCASE_A + && LEXER_TO_ASCII_LOWERCASE (ch) <= LIT_CHAR_LOWERCASE_Z) + { + digit = LEXER_TO_ASCII_LOWERCASE (ch) - LIT_CHAR_LOWERCASE_A + 10; + } + else + { + /* Not a valid digit char, set to invalid value */ + digit = radix; + } + + if (digit >= radix) + { + break; + } + + value *= radix; + value += digit; + + str_p++; + } + + /* 12. */ + if (str_p == digit_start_p) + { + return ecma_make_nan_value (); + } + + /* 15. */ + if (sign) + { + value *= ECMA_NUMBER_MINUS_ONE; + } + + return ecma_make_number_value (value); +} /* ecma_number_parse_int */ + +/** + * The Number object's 'parseFloat' routine + * + * See also: + * ECMA-262 v5, 15.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_number_parse_float (const lit_utf8_byte_t *str_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t str_size) /**< routine's first argument's + * string buffer's size */ +{ + /* 2. Remove leading whitespace. */ + ecma_string_trim_helper (&str_p, &str_size); + + const lit_utf8_byte_t *str_end_p = str_p + str_size; + bool sign = false; + + if (str_size == 0) + { + return ecma_make_nan_value (); + } + + if (*str_p == LIT_CHAR_PLUS) + { + str_p++; + } + else if (*str_p == LIT_CHAR_MINUS) + { + sign = true; + str_p++; + } + + /* Check if string is equal to "Infinity". */ + const lit_utf8_byte_t *infinity_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL); + const lit_utf8_size_t infinity_length = lit_get_magic_string_size (LIT_MAGIC_STRING_INFINITY_UL); + + /* The input string should be at least the length of "Infinity" to be correctly processed as + * the infinity value. + */ + if ((lit_utf8_size_t) (str_end_p - str_p) >= infinity_length && memcmp (infinity_str_p, str_p, infinity_length) == 0) + { + return ecma_make_number_value (ecma_number_make_infinity (sign)); + } + + const lit_utf8_byte_t *num_start_p = str_p; + const lit_utf8_byte_t *num_end_p = str_p; + + while (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + } + + if (str_p < str_end_p && *str_p == LIT_CHAR_DOT) + { + str_p++; + + while (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + } + } + + num_end_p = str_p; + + if (str_p < str_end_p && LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_E) + { + str_p++; + + if (str_p < str_end_p && (*str_p == LIT_CHAR_PLUS || *str_p == LIT_CHAR_MINUS)) + { + str_p++; + } + + if (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + + while (str_p < str_end_p && lit_char_is_decimal_digit (*str_p)) + { + str_p++; + } + + num_end_p = str_p; + } + } + + lit_utf8_size_t num_size = (lit_utf8_size_t) (num_end_p - num_start_p); + + if (num_size == 0) + { + return ecma_make_nan_value (); + } + + /* 5. */ + ecma_number_t ret_num = ecma_utf8_string_to_number (num_start_p, num_size, 0); + + if (sign) + { + ret_num *= ECMA_NUMBER_MINUS_ONE; + } + + return ecma_make_number_value (ret_num); +} /* ecma_number_parse_float */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.h new file mode 100644 index 00000000..19ac8b51 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-number.h @@ -0,0 +1,245 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_HELPERS_NUMBER_H +#define ECMA_HELPERS_NUMBER_H + +#include "ecma-globals.h" + +#include "jerry-config.h" + +/** + * Binary representation of an ecma-number + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +typedef uint64_t ecma_binary_num_t; +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +typedef uint32_t ecma_binary_num_t; +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Makes it possible to read/write the binary representation of an ecma_number_t + * without strict aliasing rule violation. + */ +typedef union +{ + ecma_number_t as_number; /**< ecma-number */ + ecma_binary_num_t as_binary; /**< binary representation */ +} ecma_number_accessor_t; + +ecma_binary_num_t ecma_number_to_binary (ecma_number_t number); +ecma_number_t ecma_number_from_binary (ecma_binary_num_t binary); + +bool ecma_number_sign (ecma_binary_num_t binary); +uint32_t ecma_number_biased_exp (ecma_binary_num_t binary); +uint64_t ecma_number_fraction (ecma_binary_num_t binary); +ecma_number_t ecma_number_create (bool sign, uint32_t biased_exp, uint64_t fraction); + +/** + * Maximum number of significant decimal digits that an ecma-number can store + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MAX_DIGITS (19) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MAX_DIGITS (9) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Width of sign field + * + * See also: + * IEEE-754 2008, 3.6, Table 3.5 + */ +#define ECMA_NUMBER_SIGN_WIDTH (1) + +/** + * Width of biased exponent field + * + * See also: + * IEEE-754 2008, 3.6, Table 3.5 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_BIASED_EXP_WIDTH (11) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_BIASED_EXP_WIDTH (8) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Exponent bias + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_EXPONENT_BIAS (1023) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_EXPONENT_BIAS (127) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Width of fraction field + * + * See also: + * IEEE-754 2008, 3.6, Table 3.5 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_FRACTION_WIDTH (52) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_FRACTION_WIDTH (23) +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Sign bit in ecma-numbers + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_SIGN_BIT 0x8000000000000000ull +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_SIGN_BIT 0x7f800000u +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Binary representation of an IEEE-754 QNaN value. + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_BINARY_QNAN 0x7ff8000000000000ull +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_BINARY_QNAN 0x7fc00000u +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Binary representation of an IEEE-754 Infinity value. + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_BINARY_INF 0x7ff0000000000000ull +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_BINARY_INF 0x7f800000u +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Binary representation of an IEEE-754 zero value. + */ +#define ECMA_NUMBER_BINARY_ZERO 0x0ull + +/** + * Number.MIN_VALUE (i.e., the smallest positive value of ecma-number) + * + * See also: ECMA_262 v5, 15.7.3.3 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MIN_VALUE ((ecma_number_t) 5e-324) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MIN_VALUE (FLT_MIN) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MAX_VALUE (i.e., the maximum value of ecma-number) + * + * See also: ECMA_262 v5, 15.7.3.2 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MAX_VALUE ((ecma_number_t) 1.7976931348623157e+308) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MAX_VALUE (FLT_MAX) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.EPSILON + * + * See also: ECMA_262 v6, 20.1.2.1 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_EPSILON ((ecma_number_t) 2.2204460492503130808472633361816e-16) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_EPSILON ((ecma_number_t) 1.1920928955078125e-7) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MAX_SAFE_INTEGER + * + * See also: ECMA_262 v6, 20.1.2.6 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0x1FFFFFFFFFFFFF) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0xFFFFFF) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MIN_SAFE_INTEGER + * + * See also: ECMA_262 v6, 20.1.2.8 + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0x1FFFFFFFFFFFFF) +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0xFFFFFF) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MAX_VALUE exponent part + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define NUMBER_MAX_DECIMAL_EXPONENT 308 +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define NUMBER_MAX_DECIMAL_EXPONENT 38 +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Number.MIN_VALUE exponent part + */ +#if JERRY_NUMBER_TYPE_FLOAT64 +#define NUMBER_MIN_DECIMAL_EXPONENT -324 +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define NUMBER_MIN_DECIMAL_EXPONENT -45 +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Euler number + */ +#define ECMA_NUMBER_E ((ecma_number_t) 2.7182818284590452354) + +/** + * Natural logarithm of 10 + */ +#define ECMA_NUMBER_LN10 ((ecma_number_t) 2.302585092994046) + +/** + * Natural logarithm of 2 + */ +#define ECMA_NUMBER_LN2 ((ecma_number_t) 0.6931471805599453) + +/** + * Logarithm base 2 of the Euler number + */ +#define ECMA_NUMBER_LOG2E ((ecma_number_t) 1.4426950408889634) + +/** + * Logarithm base 10 of the Euler number + */ +#define ECMA_NUMBER_LOG10E ((ecma_number_t) 0.4342944819032518) + +/** + * Pi number + */ +#define ECMA_NUMBER_PI ((ecma_number_t) 3.1415926535897932) + +/** + * Square root of 0.5 + */ +#define ECMA_NUMBER_SQRT_1_2 ((ecma_number_t) 0.7071067811865476) + +/** + * Square root of 2 + */ +#define ECMA_NUMBER_SQRT2 ((ecma_number_t) 1.4142135623730951) + +#endif /* !ECMA_HELPERS_NUMBER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-string.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-string.cpp new file mode 100644 index 00000000..2b186a8e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-string.cpp @@ -0,0 +1,2780 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +JERRY_STATIC_ASSERT ((((int)ECMA_STRING_CONTAINER_MASK) >= ((int)ECMA_STRING_CONTAINER__MAX)), + ecma_string_container_types_must_be_lower_than_the_container_mask); + +JERRY_STATIC_ASSERT (((ECMA_STRING_MAX_REF | ECMA_STRING_CONTAINER_MASK | ECMA_STATIC_STRING_FLAG) == UINT32_MAX), + ecma_string_ref_and_container_fields_should_fill_the_32_bit_field); + +JERRY_STATIC_ASSERT (((uint32_t)ECMA_STRING_NOT_ARRAY_INDEX == UINT32_MAX), + ecma_string_not_array_index_must_be_equal_to_uint32_max); + +JERRY_STATIC_ASSERT ((ECMA_TYPE_DIRECT_STRING & 0x1) != 0, ecma_type_direct_string_must_be_odd_number); + +JERRY_STATIC_ASSERT ((((int)LIT_MAGIC_STRING__COUNT) <= ((int)ECMA_DIRECT_STRING_MAX_IMM)), + all_magic_strings_must_be_encoded_as_direct_string); + +JERRY_STATIC_ASSERT (((int) ECMA_DIRECT_STRING_UINT == (int) ECMA_STRING_CONTAINER_UINT32_IN_DESC), + ecma_direct_and_container_types_must_match); + +JERRY_STATIC_ASSERT ((((int)ECMA_PROPERTY_NAME_TYPE_SHIFT) > ((int)ECMA_VALUE_SHIFT)), + ecma_property_name_type_shift_must_be_greater_than_ecma_value_shift); + +JERRY_STATIC_ASSERT ((sizeof (ecma_stringbuilder_header_t) <= ECMA_ASCII_STRING_HEADER_SIZE), + ecma_stringbuilder_header_must_not_be_larger_than_ecma_ascii_string); + +/** + * Convert a string to an unsigned 32 bit value if possible + * + * @return true if the conversion is successful + * false otherwise + */ +static bool +ecma_string_to_array_index (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size, /**< string size */ + uint32_t *result_p) /**< [out] converted value */ +{ + JERRY_ASSERT (string_size > 0 && *string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9); + + if (*string_p == LIT_CHAR_0) + { + *result_p = 0; + return (string_size == 1); + } + + if (string_size > ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + return false; + } + + uint32_t index = 0; + const lit_utf8_byte_t *string_end_p = string_p + string_size; + + if (string_size == ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + string_end_p--; + } + + do + { + if (*string_p > LIT_CHAR_9 || *string_p < LIT_CHAR_0) + { + return false; + } + + index = (index * 10) + (uint32_t) (*string_p++ - LIT_CHAR_0); + } while (string_p < string_end_p); + + if (string_size < ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + *result_p = index; + return true; + } + + /* Overflow must be checked as well when size is + * equal to ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32. */ + if (*string_p > LIT_CHAR_9 || *string_p < LIT_CHAR_0 || index > (UINT32_MAX / 10) + || (index == (UINT32_MAX / 10) && *string_p > LIT_CHAR_5)) + { + return false; + } + + *result_p = (index * 10) + (uint32_t) (*string_p - LIT_CHAR_0); + return true; +} /* ecma_string_to_array_index */ + +/** + * Returns the characters and size of a string. + * + * Note: + * UINT type is not supported + * + * @return byte array start - if the byte array of a string is available + * NULL - otherwise + */ +static const lit_utf8_byte_t * +ecma_string_get_chars_fast (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t *size_p) /**< [out] size of the ecma string */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + if (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC) + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id >= LIT_MAGIC_STRING__COUNT) + { + id -= LIT_MAGIC_STRING__COUNT; + + *size_p = lit_get_magic_string_ex_size (id); + return lit_get_magic_string_ex_utf8 (id); + } + + *size_p = lit_get_magic_string_size (id); + return lit_get_magic_string_utf8 (id); + } + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + *size_p = ((ecma_short_string_t *) string_p)->size; + return ECMA_SHORT_STRING_GET_BUFFER (string_p); + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + *size_p = long_string_p->size; + return long_string_p->string_p; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + *size_p = ECMA_ASCII_STRING_GET_SIZE (string_p); + return ECMA_ASCII_STRING_GET_BUFFER (string_p); + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + *size_p = lit_get_magic_string_ex_size (id); + return lit_get_magic_string_ex_utf8 (id); + } + } +} /* ecma_string_get_chars_fast */ + +/** + * Allocate new ecma-string and fill it with reference to ECMA magic string + * + * @return pointer to ecma-string descriptor + */ +static ecma_string_t * +ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t id) /**< identifier of externl magic string */ +{ + JERRY_ASSERT (id < lit_get_magic_string_ex_count ()); + + uintptr_t string_id = (uintptr_t) (id + LIT_MAGIC_STRING__COUNT); + + if (JERRY_LIKELY (string_id <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, string_id); + } + + ecma_string_t *string_desc_p = ecma_alloc_string (); + + string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX | ECMA_STRING_REF_ONE; + string_desc_p->u.magic_string_ex_id = id + LIT_MAGIC_STRING__COUNT; + + return string_desc_p; +} /* ecma_new_ecma_string_from_magic_string_ex_id */ + +/** + * Allocate new ecma-string and fill it with reference to the symbol descriptor + * + * Note: + * Takes the reference to the string_desc + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc) /**< ecma-string */ +{ + JERRY_ASSERT (!ecma_is_value_symbol (string_desc)); + + ecma_extended_string_t *symbol_p = ecma_alloc_extended_string (); + symbol_p->header.refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_SYMBOL; + symbol_p->u.symbol_descriptor = string_desc; + symbol_p->header.u.hash = (lit_string_hash_t) (((uintptr_t) symbol_p) & (uintptr_t) ~ECMA_SYMBOL_FLAGS_MASK); + + return (ecma_string_t *) symbol_p; +} /* ecma_new_symbol_from_descriptor_string */ + +/** + * Check whether an ecma-string contains an ecma-symbol + * + * @return true - if the ecma-string contains an ecma-symbol + * false - otherwise + */ +bool +ecma_prop_name_is_symbol (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + + return (!ECMA_IS_DIRECT_STRING (string_p) && ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_SYMBOL); +} /* ecma_prop_name_is_symbol */ + +/** + * Allocate new UTF8 ecma-string and fill it with characters from the given utf8 buffer + * + * @return pointer to ecma-string descriptor + */ +static inline ecma_string_t * +ecma_new_ecma_string_from_utf8_buffer (lit_utf8_size_t length, /**< length of the buffer */ + lit_utf8_size_t size, /**< size of the buffer */ + lit_utf8_byte_t **data_p) /**< [out] pointer to the start of the string buffer */ +{ + if (JERRY_LIKELY (size <= UINT16_MAX)) + { + if (JERRY_LIKELY (length == size) && size <= (UINT8_MAX + 1)) + { + ecma_string_t *string_desc_p; + string_desc_p = (ecma_string_t *) ecma_alloc_string_buffer (size + ECMA_ASCII_STRING_HEADER_SIZE); + string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_ASCII_STRING | ECMA_STRING_REF_ONE; + ECMA_ASCII_STRING_SET_SIZE (string_desc_p, size); + + *data_p = ECMA_ASCII_STRING_GET_BUFFER (string_desc_p); + return (ecma_string_t *) string_desc_p; + } + + ecma_short_string_t *string_desc_p; + string_desc_p = (ecma_short_string_t *) ecma_alloc_string_buffer (size + sizeof (ecma_short_string_t)); + string_desc_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; + string_desc_p->size = (uint16_t) size; + string_desc_p->length = (uint16_t) length; + + *data_p = ECMA_SHORT_STRING_GET_BUFFER (string_desc_p); + return (ecma_string_t *) string_desc_p; + } + + ecma_long_string_t *long_string_p; + long_string_p = (ecma_long_string_t *) ecma_alloc_string_buffer (size + sizeof (ecma_long_string_t)); + long_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING | ECMA_STRING_REF_ONE; + long_string_p->string_p = ECMA_LONG_STRING_BUFFER_START (long_string_p); + long_string_p->size = size; + long_string_p->length = length; + + *data_p = ECMA_LONG_STRING_BUFFER_START (long_string_p); + return (ecma_string_t *) long_string_p; +} /* ecma_new_ecma_string_from_utf8_buffer */ + +/** + * Checks whether a string has a special representation, that is, the string is either a magic string, + * an external magic string, or an uint32 number, and creates an ecma string using the special representation, + * if available. + * + * @return pointer to ecma string with the special representation + * NULL, if there is no special representation for the string + */ +static ecma_string_t * +ecma_find_special_string (const lit_utf8_byte_t *string_p, /**< utf8 string */ + lit_utf8_size_t string_size) /**< string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + lit_magic_string_id_t magic_string_id = lit_is_utf8_string_magic (string_p, string_size); + + if (magic_string_id != LIT_MAGIC_STRING__COUNT) + { + return ecma_get_magic_string (magic_string_id); + } + + JERRY_ASSERT (string_size > 0); + + if (*string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9) + { + uint32_t array_index; + + if (ecma_string_to_array_index (string_p, string_size, &array_index)) + { + return ecma_new_ecma_string_from_uint32 (array_index); + } + } + + if (lit_get_magic_string_ex_count () > 0) + { + lit_magic_string_ex_id_t magic_string_ex_id = lit_is_ex_utf8_string_magic (string_p, string_size); + + if (magic_string_ex_id < lit_get_magic_string_ex_count ()) + { + return ecma_new_ecma_string_from_magic_string_ex_id (magic_string_ex_id); + } + } + + return NULL; +} /* ecma_find_special_string */ + +/** + * Allocate new ecma-string and fill it with characters from ascii characters + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_ascii (const lit_utf8_byte_t *string_p, /**< ascii string */ + lit_utf8_size_t string_size) /**< string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + + ecma_string_t *string_desc_p = ecma_find_special_string (string_p, string_size); + + if (string_desc_p != NULL) + { + return string_desc_p; + } + + lit_utf8_byte_t *data_p; + string_desc_p = ecma_new_ecma_string_from_utf8_buffer (string_size, string_size, &data_p); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (string_p, string_size); + memcpy (data_p, string_p, string_size); + + return string_desc_p; +} /* ecma_new_ecma_string_from_ascii */ + +/** + * Allocate new ecma-string and fill it with characters from the utf8 string + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size)); + + ecma_string_t *string_desc_p = ecma_find_special_string (string_p, string_size); + + if (string_desc_p != NULL) + { + return string_desc_p; + } + + lit_utf8_byte_t *data_p; + string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (lit_utf8_string_length (string_p, string_size), string_size, &data_p); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (string_p, string_size); + memcpy (data_p, string_p, string_size); + + return string_desc_p; +} /* ecma_new_ecma_string_from_utf8 */ + +/** + * Allocate a new ecma-string and initialize it from the utf8 string argument. + * All 4-bytes long unicode sequences are converted into two 3-bytes long sequences. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< utf-8 string size */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + + lit_utf8_size_t converted_string_length = 0; + lit_utf8_size_t converted_string_size = 0; + lit_utf8_size_t pos = 0; + + /* Calculate the required length and size information of the converted cesu-8 encoded string */ + while (pos < string_size) + { + if ((string_p[pos] & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + pos++; + } + else if ((string_p[pos] & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + pos += 2; + } + else if ((string_p[pos] & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + pos += 3; + } + else + { + JERRY_ASSERT ((string_p[pos] & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER); + pos += 4; + converted_string_size += 2; + converted_string_length++; + } + + converted_string_length++; + } + + JERRY_ASSERT (pos == string_size); + + if (converted_string_size == 0) + { + return ecma_new_ecma_string_from_utf8 (string_p, string_size); + } + + converted_string_size += string_size; + + JERRY_ASSERT (lit_is_valid_utf8_string (string_p, string_size, false)); + + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (converted_string_length, converted_string_size, &data_p); + + const lit_utf8_byte_t *const begin_data_p = data_p; + pos = 0; + + while (pos < string_size) + { + if ((string_p[pos] & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) + { + /* Processing 4 byte unicode sequence. Always converted to two 3 byte long sequence. */ + lit_four_byte_utf8_char_to_cesu8 (data_p, string_p + pos); + data_p += 3 * 2; + pos += 4; + } + else + { + *data_p++ = string_p[pos++]; + } + } + + JERRY_ASSERT (pos == string_size); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (begin_data_p, converted_string_size); + + return (ecma_string_t *) string_desc_p; +} /* ecma_new_ecma_string_from_utf8_converted_to_cesu8 */ + +/** + * Allocate new ecma-external-string and fill it with characters from the cesu8 string + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, /**< cesu-8 string */ + lit_utf8_size_t string_size, /**< string size */ + void *user_p) /**< user pointer passed to the callback + * when the string is freed */ +{ + JERRY_ASSERT (string_p != NULL || string_size == 0); + JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size)); + + if (string_size < (sizeof (ecma_external_string_t) - sizeof (ecma_short_string_t))) + { + /* Normal strings are created for short strings. */ + ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8 (string_p, string_size); + + jerry_external_string_free_cb_t free_cb = JERRY_CONTEXT (external_string_free_callback_p); + + if (free_cb != NULL) + { + free_cb ((lit_utf8_byte_t *) string_p, string_size, user_p); + } + return string_desc_p; + } + + ecma_string_t *string_desc_p = ecma_find_special_string (string_p, string_size); + + if (string_desc_p != NULL) + { + jerry_external_string_free_cb_t free_cb = JERRY_CONTEXT (external_string_free_callback_p); + + if (free_cb != NULL) + { + free_cb ((lit_utf8_byte_t *) string_p, string_size, user_p); + } + return string_desc_p; + } + + ecma_external_string_t *external_string_p = ecma_alloc_external_string (); + ecma_long_string_t *long_string_p = (ecma_long_string_t *) external_string_p; + + long_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING | ECMA_STRING_REF_ONE; + long_string_p->header.u.hash = lit_utf8_string_calc_hash (string_p, string_size); + long_string_p->string_p = string_p; + long_string_p->size = string_size; + long_string_p->length = lit_utf8_string_length (string_p, string_size); + external_string_p->user_p = user_p; + + return (ecma_string_t *) external_string_p; +} /* ecma_new_ecma_external_string_from_cesu8 */ + +/** + * Allocate new ecma-string and fill it with cesu-8 character which represents specified code unit + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit) /**< code unit */ +{ + lit_utf8_byte_t lit_utf8_bytes[LIT_UTF8_MAX_BYTES_IN_CODE_UNIT]; + lit_utf8_size_t bytes_size = lit_code_unit_to_utf8 (code_unit, lit_utf8_bytes); + + return ecma_new_ecma_string_from_utf8 (lit_utf8_bytes, bytes_size); +} /* ecma_new_ecma_string_from_code_unit */ + +/** + * Allocate new ecma-string and fill it with cesu-8 character which represents specified code units + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, /**< code unit */ + ecma_char_t second_code_unit) /**< code unit */ +{ + lit_utf8_byte_t lit_utf8_bytes[2 * LIT_UTF8_MAX_BYTES_IN_CODE_UNIT]; + lit_utf8_size_t bytes_size = lit_code_unit_to_utf8 (first_code_unit, lit_utf8_bytes); + bytes_size += lit_code_unit_to_utf8 (second_code_unit, lit_utf8_bytes + bytes_size); + + return ecma_new_ecma_string_from_utf8 (lit_utf8_bytes, bytes_size); +} /* ecma_new_ecma_string_from_code_units */ + +/** + * Allocate new ecma-string and fill it with ecma-number + * + * Note: the number cannot be represented as direct string + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_non_direct_string_from_uint32 (uint32_t uint32_number) /**< uint32 value of the string */ +{ + JERRY_ASSERT (uint32_number > ECMA_DIRECT_STRING_MAX_IMM); + + ecma_string_t *string_p = ecma_alloc_string (); + + string_p->refs_and_container = ECMA_STRING_CONTAINER_UINT32_IN_DESC | ECMA_STRING_REF_ONE; + string_p->u.uint32_number = uint32_number; + + return string_p; +} /* ecma_new_non_direct_string_from_uint32 */ + +/** + * Allocate new ecma-string and fill it with property length number + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_length (ecma_length_t number) /**< property length */ +{ + if (JERRY_LIKELY (number <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) number); + } + + JERRY_ASSERT ((ecma_number_t) number <= ECMA_NUMBER_MAX_SAFE_INTEGER); + + if (JERRY_UNLIKELY (number > UINT32_MAX)) + { + return ecma_new_ecma_string_from_number ((ecma_number_t) number); + } + + return ecma_new_non_direct_string_from_uint32 ((uint32_t) number); +} /* ecma_new_ecma_string_from_length */ + +/** + * Allocate new ecma-string and fill it with uint32 number + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_uint32 (uint32_t uint32_number) /**< uint32 value of the string */ +{ + if (JERRY_LIKELY (uint32_number <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number); + } + + return ecma_new_non_direct_string_from_uint32 (uint32_number); +} /* ecma_new_ecma_string_from_uint32 */ + +/** + * Returns the constant assigned to the uint32 number. + * + * Note: + * Calling ecma_deref_ecma_string on the returned pointer is optional. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_get_ecma_string_from_uint32 (uint32_t uint32_number) /**< input number */ +{ + JERRY_ASSERT (uint32_number <= ECMA_DIRECT_STRING_MAX_IMM); + + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number); +} /* ecma_get_ecma_string_from_uint32 */ + +/** + * Allocate new ecma-string and fill it with ecma-number + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ +{ + uint32_t uint32_num = ecma_number_to_uint32 (num); + if (num == ((ecma_number_t) uint32_num)) + { + return ecma_new_ecma_string_from_uint32 (uint32_num); + } + + if (ecma_number_is_nan (num)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_NAN); + } + + if (ecma_number_is_infinity (num)) + { + lit_magic_string_id_t id = + (ecma_number_is_negative (num) ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL : LIT_MAGIC_STRING_INFINITY_UL); + return ecma_get_magic_string (id); + } + + lit_utf8_byte_t str_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + lit_utf8_size_t str_size = ecma_number_to_utf8_string (num, str_buf, sizeof (str_buf)); + + JERRY_ASSERT (str_size > 0); +#ifndef JERRY_NDEBUG + JERRY_ASSERT (lit_is_utf8_string_magic (str_buf, str_size) == LIT_MAGIC_STRING__COUNT + && lit_is_ex_utf8_string_magic (str_buf, str_size) == lit_get_magic_string_ex_count ()); +#endif /* !JERRY_NDEBUG */ + + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (lit_utf8_string_length (str_buf, str_size), str_size, &data_p); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (str_buf, str_size); + memcpy (data_p, str_buf, str_size); + + return string_desc_p; +} /* ecma_new_ecma_string_from_number */ + +/** + * Returns the constant assigned to the magic string id. + * + * Note: + * Calling ecma_deref_ecma_string on the returned pointer is optional. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_get_magic_string (lit_magic_string_id_t id) /**< identifier of magic string */ +{ + JERRY_ASSERT (id < LIT_MAGIC_STRING__COUNT); + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, (uintptr_t) id); +} /* ecma_get_magic_string */ + +/** + * Returns the constant assigned to the internal magic string id. + * + * Note: + * Calling ecma_deref_ecma_string on the returned pointer is optional. + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_get_internal_string (lit_magic_string_id_t id) /**< identifier of magic string */ +{ + JERRY_ASSERT (id >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT && id < LIT_MAGIC_STRING__COUNT); + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_SPECIAL, (uintptr_t) id); +} /* ecma_get_internal_string */ + +/** + * Append a cesu8 string after an ecma-string + * + * Note: + * The string1_p argument is freed. If it needs to be preserved, + * call ecma_ref_ecma_string with string1_p before the call. + * + * @return concatenation of an ecma-string and a cesu8 string + */ +ecma_string_t * +ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ + const lit_utf8_byte_t *cesu8_string2_p, /**< characters to be appended */ + lit_utf8_size_t cesu8_string2_size, /**< byte size of cesu8_string2_p */ + lit_utf8_size_t cesu8_string2_length) /**< character length of cesu8_string2_p */ +{ + JERRY_ASSERT (string1_p != NULL && cesu8_string2_size > 0 && cesu8_string2_length > 0); + + if (JERRY_UNLIKELY (ecma_string_is_empty (string1_p))) + { + return ecma_new_ecma_string_from_utf8 (cesu8_string2_p, cesu8_string2_size); + } + + lit_utf8_size_t cesu8_string1_size; + lit_utf8_size_t cesu8_string1_length; + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + + const lit_utf8_byte_t *cesu8_string1_p = + ecma_string_get_chars (string1_p, &cesu8_string1_size, &cesu8_string1_length, uint32_to_string_buffer, &flags); + + JERRY_ASSERT (!(flags & ECMA_STRING_FLAG_MUST_BE_FREED)); + JERRY_ASSERT (cesu8_string1_length > 0); + JERRY_ASSERT (cesu8_string1_length <= cesu8_string1_size); + + lit_utf8_size_t new_size = cesu8_string1_size + cesu8_string2_size; + + /* Poor man's carry flag check: it is impossible to allocate this large string. */ + if (new_size < (cesu8_string1_size | cesu8_string2_size)) + { + jerry_fatal (JERRY_FATAL_OUT_OF_MEMORY); + } + + lit_magic_string_id_t magic_string_id; + magic_string_id = + lit_is_utf8_string_pair_magic (cesu8_string1_p, cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + if (magic_string_id != LIT_MAGIC_STRING__COUNT) + { + ecma_deref_ecma_string (string1_p); + return ecma_get_magic_string (magic_string_id); + } + + if ((flags & ECMA_STRING_FLAG_IS_UINT32) && new_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + { + memcpy (uint32_to_string_buffer + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + uint32_t array_index; + + if (ecma_string_to_array_index (uint32_to_string_buffer, new_size, &array_index)) + { + ecma_deref_ecma_string (string1_p); + return ecma_new_ecma_string_from_uint32 (array_index); + } + } + + if (lit_get_magic_string_ex_count () > 0) + { + lit_magic_string_ex_id_t magic_string_ex_id; + magic_string_ex_id = + lit_is_ex_utf8_string_pair_magic (cesu8_string1_p, cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + if (magic_string_ex_id < lit_get_magic_string_ex_count ()) + { + ecma_deref_ecma_string (string1_p); + return ecma_new_ecma_string_from_magic_string_ex_id (magic_string_ex_id); + } + } + + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = + ecma_new_ecma_string_from_utf8_buffer (cesu8_string1_length + cesu8_string2_length, new_size, &data_p); + + lit_string_hash_t hash_start; + + if (JERRY_UNLIKELY (flags & ECMA_STRING_FLAG_REHASH_NEEDED)) + { + hash_start = lit_utf8_string_calc_hash (cesu8_string1_p, cesu8_string1_size); + } + else + { + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p)); + hash_start = string1_p->u.hash; + } + + string_desc_p->u.hash = lit_utf8_string_hash_combine (hash_start, cesu8_string2_p, cesu8_string2_size); + + memcpy (data_p, cesu8_string1_p, cesu8_string1_size); + memcpy (data_p + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); + + ecma_deref_ecma_string (string1_p); + return (ecma_string_t *) string_desc_p; +} /* ecma_append_chars_to_string */ + +/** + * Concatenate ecma-strings + * + * Note: + * The string1_p argument is freed. If it needs to be preserved, + * call ecma_ref_ecma_string with string1_p before the call. + * + * @return concatenation of two ecma-strings + */ +ecma_string_t * +ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ + ecma_string_t *string2_p) /**< second ecma-string */ +{ + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); + + if (JERRY_UNLIKELY (ecma_string_is_empty (string1_p))) + { + ecma_ref_ecma_string (string2_p); + return string2_p; + } + else if (JERRY_UNLIKELY (ecma_string_is_empty (string2_p))) + { + return string1_p; + } + + lit_utf8_size_t cesu8_string2_size; + lit_utf8_size_t cesu8_string2_length; + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; + + const lit_utf8_byte_t *cesu8_string2_p = + ecma_string_get_chars (string2_p, &cesu8_string2_size, &cesu8_string2_length, uint32_to_string_buffer, &flags); + + JERRY_ASSERT (cesu8_string2_p != NULL); + + ecma_string_t *result_p = + ecma_append_chars_to_string (string1_p, cesu8_string2_p, cesu8_string2_size, cesu8_string2_length); + + JERRY_ASSERT (!(flags & ECMA_STRING_FLAG_MUST_BE_FREED)); + + return result_p; +} /* ecma_concat_ecma_strings */ + +/** + * Increase reference counter of non-direct ecma-string. + * + * @return void + */ +void +ecma_ref_ecma_string_non_direct (ecma_string_t *string_p) /**< string descriptor */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string_p)); + +#ifdef JERRY_NDEBUG + if (ECMA_STRING_IS_STATIC (string_p)) + { + return; + } +#endif /* JERRY_NDEBUG */ + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (JERRY_LIKELY (string_p->refs_and_container < ECMA_STRING_MAX_REF)) + { + /* Increase reference counter. */ + string_p->refs_and_container += ECMA_STRING_REF_ONE; + } + else + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } +} /* ecma_ref_ecma_string_non_direct */ + +/** + * Increase reference counter of ecma-string. + */ +void +ecma_ref_ecma_string (ecma_string_t *string_p) /**< string descriptor */ +{ + JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return; + } + + ecma_ref_ecma_string_non_direct (string_p); +} /* ecma_ref_ecma_string */ + +/** + * Decrease reference counter and deallocate a non-direct ecma-string + * if the counter becomes zero. + * + * @return void + */ +void +ecma_deref_ecma_string_non_direct (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string_p)); + +#ifdef JERRY_NDEBUG + if (ECMA_STRING_IS_STATIC (string_p)) + { + return; + } +#endif /* JERRY_NDEBUG */ + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + /* Decrease reference counter. */ + string_p->refs_and_container -= ECMA_STRING_REF_ONE; + + if (string_p->refs_and_container >= ECMA_STRING_REF_ONE) + { + return; + } + + ecma_destroy_ecma_string (string_p); +} /* ecma_deref_ecma_string_non_direct */ + +/** + * Decrease reference counter and deallocate ecma-string + * if the counter becomes zero. + */ +void +ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return; + } + + ecma_deref_ecma_string_non_direct (string_p); +} /* ecma_deref_ecma_string */ + +/** + * Deallocate an ecma-string + */ +void +ecma_destroy_ecma_string (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string_p)); + JERRY_ASSERT ((string_p->refs_and_container < ECMA_STRING_REF_ONE) || ECMA_STRING_IS_STATIC (string_p)); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_dealloc_string_buffer (string_p, ((ecma_short_string_t *) string_p)->size + sizeof (ecma_short_string_t)); + return; + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + + if (long_string_p->string_p == ECMA_LONG_STRING_BUFFER_START (long_string_p)) + { + ecma_dealloc_string_buffer (string_p, long_string_p->size + sizeof (ecma_long_string_t)); + return; + } + + ecma_external_string_t *external_string_p = (ecma_external_string_t *) string_p; + jerry_external_string_free_cb_t free_cb = JERRY_CONTEXT (external_string_free_callback_p); + + if (free_cb != NULL) + { + free_cb ((lit_utf8_byte_t *) external_string_p->header.string_p, + external_string_p->header.size, + external_string_p->user_p); + } + + ecma_dealloc_external_string (external_string_p); + return; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + ecma_dealloc_string_buffer (string_p, ECMA_ASCII_STRING_GET_SIZE (string_p) + ECMA_ASCII_STRING_HEADER_SIZE); + return; + } + case ECMA_STRING_CONTAINER_SYMBOL: + { + ecma_extended_string_t *symbol_p = (ecma_extended_string_t *) string_p; + ecma_free_value (symbol_p->u.symbol_descriptor); + ecma_dealloc_extended_string (symbol_p); + return; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC + || ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + /* only the string descriptor itself should be freed */ + ecma_dealloc_string (string_p); + } + } +} /* ecma_destroy_ecma_string */ + +/** + * Convert ecma-string to number + * + * @return converted ecma-number + */ +ecma_number_t +ecma_string_to_number (const ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_UINT)) + { + return (ecma_number_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + } + } + else if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ((ecma_number_t) string_p->u.uint32_number); + } + + lit_utf8_size_t size; + const lit_utf8_byte_t *chars_p = ecma_string_get_chars_fast (string_p, &size); + + JERRY_ASSERT (chars_p != NULL); + + if (size == 0) + { + return ECMA_NUMBER_ZERO; + } + + return ecma_utf8_string_to_number (chars_p, size, 0); +} /* ecma_string_to_number */ + +/** + * Check if string is array index. + * + * @return ECMA_STRING_NOT_ARRAY_INDEX if string is not array index + * the array index otherwise + */ +uint32_t +ecma_string_get_array_index (const ecma_string_t *str_p) /**< ecma-string */ +{ + if (ECMA_IS_DIRECT_STRING (str_p)) + { + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (str_p, ECMA_DIRECT_STRING_UINT)) + { + /* Value cannot be equal to the maximum value of a 32 bit unsigned number. */ + return (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (str_p); + } + + return ECMA_STRING_NOT_ARRAY_INDEX; + } + + if (ECMA_STRING_GET_CONTAINER (str_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + /* When the uint32_number is equal to the maximum value of 32 bit unsigned integer number, + * it is also an invalid array index. The comparison to ECMA_STRING_NOT_ARRAY_INDEX will + * be true in this case. */ + return str_p->u.uint32_number; + } + + return ECMA_STRING_NOT_ARRAY_INDEX; +} /* ecma_string_get_array_index */ + +/** + * Copy digits of uint32 number, truncating if buffer is not large enough. + * + * @return number of digits copied + */ +static lit_utf8_size_t +ecma_uint32_to_buffer (uint32_t num, /**< number */ + lit_utf8_byte_t *buffer_p /**< destination buffer */, + lit_utf8_size_t buffer_size /**< buffer size */) +{ + lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_size_t digit_count = ecma_uint32_to_utf8_string (num, digits, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + digit_count = JERRY_MIN (buffer_size, digit_count); + memcpy (buffer_p, digits, digit_count); + return digit_count; +} /* ecma_uint32_to_buffer */ + +/** + * Convert ecma-string's contents to the specified encoding and copy it to the buffer. + * String data will be truncated to fit the buffer. + * + * @return number of bytes copied to the buffer. + */ +lit_utf8_size_t JERRY_ATTR_WARN_UNUSED_RESULT +ecma_string_copy_to_buffer (const ecma_string_t *string_p, /**< ecma-string descriptor */ + lit_utf8_byte_t *buffer_p, /**< destination buffer pointer + * (can be NULL if buffer_size == 0) */ + lit_utf8_size_t buffer_size, /**< size of buffer */ + jerry_encoding_t encoding) /**< encoding */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (buffer_p != NULL || buffer_size == 0); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_UINT)) + { + return ecma_uint32_to_buffer ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p), buffer_p, buffer_size); + } + } + else + { + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ecma_uint32_to_buffer (string_p->u.uint32_number, buffer_p, buffer_size); + } + } + + lit_utf8_size_t string_size; + const lit_utf8_byte_t *chars_p = ecma_string_get_chars_fast (string_p, &string_size); + lit_utf8_size_t copy_size = 0; + + JERRY_ASSERT (chars_p != NULL); + + switch (encoding) + { + case JERRY_ENCODING_CESU8: + { + copy_size = JERRY_MIN (string_size, buffer_size); + + if (copy_size < string_size) + { + /* Do not copy partial characters */ + while ((chars_p[copy_size] & LIT_UTF8_EXTRA_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER) + { + copy_size--; + } + } + + memcpy (buffer_p, chars_p, copy_size); + break; + } + case JERRY_ENCODING_UTF8: + { + if (string_size == ecma_string_get_length (string_p)) + { + copy_size = JERRY_MIN (string_size, buffer_size); + + memcpy (buffer_p, chars_p, copy_size); + break; + } + + copy_size = lit_convert_cesu8_string_to_utf8_string (chars_p, string_size, buffer_p, buffer_size); + break; + } + default: + { + break; + } + } + + return copy_size; +} /* ecma_string_copy_to_buffer */ + +/** + * Convert ecma-string's contents to a cesu-8 string and put it to the buffer. + * It is the caller's responsibility to make sure that the string fits in the buffer. + * Check if the size of the string is equal with the size of the buffer. + * + * @return void + */ +void +ecma_string_to_cesu8_bytes (const ecma_string_t *string_desc_p, /**< ecma-string descriptor */ + lit_utf8_byte_t *buffer_p, /**< destination buffer pointer + * (can be NULL if buffer_size == 0) */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + const lit_utf8_size_t size = ecma_string_copy_to_buffer (string_desc_p, buffer_p, buffer_size, JERRY_ENCODING_CESU8); + JERRY_ASSERT (size == buffer_size); +} /* ecma_string_to_cesu8_bytes */ + +/** + * Get size of the uint32 number stored locally in the string's descriptor + * + * Note: the represented number size and length are equal + * + * @return size in bytes + */ +static inline lit_utf8_size_t +ecma_string_get_uint32_size (const uint32_t uint32_number) /**< number in the string-descriptor */ +{ + uint32_t prev_number = 1; + uint32_t next_number = 100; + lit_utf8_size_t size = 1; + + const uint32_t max_size = 9; + + while (size < max_size && uint32_number >= next_number) + { + prev_number = next_number; + next_number *= 100; + size += 2; + } + + if (uint32_number >= prev_number * 10) + { + size++; + } + + return size; +} /* ecma_string_get_uint32_size */ + +/** + * Checks whether the given string is a sequence of ascii characters. + */ +#define ECMA_STRING_IS_ASCII(char_p, size) ((size) == lit_utf8_string_length ((char_p), (size))) + +/** + * Returns with the cesu8 character array of a string. + * + * Note: + * - This function returns with a newly allocated buffer for uint32 strings, + * which must be freed if the optional uint32_buff_p parameter is NULL. + * - The ASCII check only happens if the flags parameter gets + * 'ECMA_STRING_FLAG_IS_ASCII' as an input. + * + * @return start of cesu8 characters + */ +const lit_utf8_byte_t * +ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t *size_p, /**< [out] size of the ecma string */ + lit_utf8_size_t *length_p, /**< [out] optional argument. If the pointer is not NULL the pointed + * memory area is filled with the length of the ecma string */ + lit_utf8_byte_t *uint32_buff_p, /**< [out] optional argument. If the pointer is not NULL the + * pointed memory area is filled with the string converted + * uint32 string descriptor */ + uint8_t *flags_p) /**< [in,out] any combination of ecma_string_flag_t bits */ +{ + lit_utf8_size_t length; + lit_utf8_size_t size; + const lit_utf8_byte_t *result_p; + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + *flags_p |= ECMA_STRING_FLAG_REHASH_NEEDED; + + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id >= LIT_MAGIC_STRING__COUNT) + { + id -= LIT_MAGIC_STRING__COUNT; + size = lit_get_magic_string_ex_size (id); + result_p = lit_get_magic_string_ex_utf8 (id); + length = 0; + + if (JERRY_UNLIKELY (*flags_p & ECMA_STRING_FLAG_IS_ASCII)) + { + length = lit_utf8_string_length (result_p, size); + } + } + else + { + size = lit_get_magic_string_size (id); + length = size; + + result_p = lit_get_magic_string_utf8 (id); + + /* All magic strings must be ascii strings. */ + JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size)); + } + break; + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + size = (lit_utf8_size_t) ecma_string_get_uint32_size (uint32_number); + + if (uint32_buff_p != NULL) + { + result_p = uint32_buff_p; + } + else + { + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + } + + length = ecma_uint32_to_utf8_string (uint32_number, (lit_utf8_byte_t *) result_p, size); + + JERRY_ASSERT (length == size); + *flags_p |= ECMA_STRING_FLAG_IS_UINT32; + break; + } + } + } + else + { + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + size = short_string_p->size; + length = short_string_p->length; + result_p = ECMA_SHORT_STRING_GET_BUFFER (short_string_p); + break; + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string_p; + size = long_string_desc_p->size; + length = long_string_desc_p->length; + result_p = long_string_desc_p->string_p; + break; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + size = ECMA_ASCII_STRING_GET_SIZE (string_p); + length = size; + result_p = ECMA_ASCII_STRING_GET_BUFFER (string_p); + break; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + size = (lit_utf8_size_t) ecma_string_get_uint32_size (string_p->u.uint32_number); + + if (uint32_buff_p != NULL) + { + result_p = uint32_buff_p; + } + else + { + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + } + + length = ecma_uint32_to_utf8_string (string_p->u.uint32_number, (lit_utf8_byte_t *) result_p, size); + + JERRY_ASSERT (length == size); + *flags_p |= ECMA_STRING_FLAG_IS_UINT32 | ECMA_STRING_FLAG_REHASH_NEEDED; + break; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + size = lit_get_magic_string_ex_size (id); + length = 0; + + if (JERRY_UNLIKELY (*flags_p & ECMA_STRING_FLAG_IS_ASCII)) + { + length = lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), size); + } + + result_p = lit_get_magic_string_ex_utf8 (id); + *flags_p |= ECMA_STRING_FLAG_REHASH_NEEDED; + break; + } + } + } + + *size_p = size; + if (length_p != NULL) + { + *length_p = length; + } + + if ((*flags_p & ECMA_STRING_FLAG_IS_ASCII) && length != size) + { + *flags_p = (uint8_t) (*flags_p & (uint8_t) ~ECMA_STRING_FLAG_IS_ASCII); + } + + return result_p; +} /* ecma_string_get_chars */ + +/** + * Checks whether the string equals to the magic string id. + * + * @return true - if the string equals to the magic string id + * false - otherwise + */ +bool +ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, /**< property name */ + lit_magic_string_id_t id) /**< magic string id */ +{ + return (string_p == ecma_get_magic_string (id)); +} /* ecma_compare_ecma_string_to_magic_id */ + +/** + * Checks whether ecma string is empty or not + * + * @return true - if the string is an empty string + * false - otherwise + */ +bool +ecma_string_is_empty (const ecma_string_t *string_p) /**< ecma-string */ +{ + return ecma_compare_ecma_string_to_magic_id (string_p, LIT_MAGIC_STRING__EMPTY); +} /* ecma_string_is_empty */ + +/** + * Checks whether the string equals to "length". + * + * @return true - if the string equals to "length" + * false - otherwise + */ +bool +ecma_string_is_length (const ecma_string_t *string_p) /**< property name */ +{ + return ecma_compare_ecma_string_to_magic_id (string_p, LIT_MAGIC_STRING_LENGTH); +} /* ecma_string_is_length */ + +/** + * Converts a property name into a string + * + * @return pointer to the converted ecma string + */ +static inline ecma_string_t * +ecma_property_to_string (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + uintptr_t property_string = ((uintptr_t) (property)) & (0x3 << ECMA_PROPERTY_NAME_TYPE_SHIFT); + property_string = (property_string >> ECMA_STRING_TYPE_CONVERSION_SHIFT) | ECMA_TYPE_DIRECT_STRING; + return (ecma_string_t *) (property_string | (((uintptr_t) prop_name_cp) << ECMA_DIRECT_STRING_SHIFT)); +} /* ecma_property_to_string */ + +/** + * Converts a string into a property name + * + * @return the compressed pointer part of the name + */ +jmem_cpointer_t +ecma_string_to_property_name (ecma_string_t *prop_name_p, /**< property name */ + ecma_property_t *name_type_p) /**< [out] property name type */ +{ + if (ECMA_IS_DIRECT_STRING (prop_name_p)) + { + *name_type_p = (ecma_property_t) ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE (prop_name_p); + return (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); + } + + *name_type_p = ECMA_DIRECT_STRING_PTR << ECMA_PROPERTY_NAME_TYPE_SHIFT; + + ecma_ref_ecma_string (prop_name_p); + + jmem_cpointer_t prop_name_cp; + ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); + return prop_name_cp; +} /* ecma_string_to_property_name */ + +/** + * Converts a property name into a string + * + * @return the string pointer + * string must be released with ecma_deref_ecma_string + */ +ecma_string_t * +ecma_string_from_property_name (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + if (ECMA_PROPERTY_GET_NAME_TYPE (property) != ECMA_DIRECT_STRING_PTR) + { + return ecma_property_to_string (property, prop_name_cp); + } + + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + ecma_ref_ecma_string (prop_name_p); + return prop_name_p; +} /* ecma_string_from_property_name */ + +/** + * Get hash code of property name + * + * @return hash code of property name + */ +lit_string_hash_t +ecma_string_get_property_name_hash (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_PTR) + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return prop_name_p->u.hash; + } + + return (lit_string_hash_t) prop_name_cp; +} /* ecma_string_get_property_name_hash */ + +/** + * Check if property name is array index. + * + * @return ECMA_STRING_NOT_ARRAY_INDEX if string is not array index + * the array index otherwise + */ +uint32_t +ecma_string_get_property_index (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) + { + case ECMA_DIRECT_STRING_UINT: + { + return (uint32_t) prop_name_cp; + } + case ECMA_DIRECT_STRING_PTR: + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return ecma_string_get_array_index (prop_name_p); + } + default: + { + return ECMA_STRING_NOT_ARRAY_INDEX; + } + } +} /* ecma_string_get_property_index */ + +/** + * Compare a property name to a string + * + * @return true if they are equals + * false otherwise + */ +bool +ecma_string_compare_to_property_name (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp, /**< property name compressed pointer */ + const ecma_string_t *string_p) /**< other string */ +{ + if (ECMA_PROPERTY_GET_NAME_TYPE (property) != ECMA_DIRECT_STRING_PTR) + { + return ecma_property_to_string (property, prop_name_cp) == string_p; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return false; + } + + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return ecma_compare_ecma_non_direct_strings (prop_name_p, string_p); +} /* ecma_string_compare_to_property_name */ + +/** + * Helper for ecma_compare_ecma_strings_longpath to get string data + * + * @return string characters + */ +static const lit_utf8_byte_t * +ecma_compare_get_string_chars (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t *size_and_length_p) /**< [out] size and length */ +{ + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + size_and_length_p[0] = short_string_p->size; + size_and_length_p[1] = short_string_p->length; + return ECMA_SHORT_STRING_GET_BUFFER (string_p); + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + size_and_length_p[0] = long_string_p->size; + size_and_length_p[1] = long_string_p->length; + return long_string_p->string_p; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + size_and_length_p[0] = ECMA_ASCII_STRING_GET_SIZE (string_p); + size_and_length_p[1] = size_and_length_p[0]; + return ECMA_ASCII_STRING_GET_BUFFER (string_p); + } + default: + { + return NULL; + } + } +} /* ecma_compare_get_string_chars */ + +/** + * Long path part of ecma-string to ecma-string comparison routine + * + * See also: + * ecma_compare_ecma_strings + * + * @return true - if strings are equal; + * false - otherwise + */ +static bool JERRY_ATTR_NOINLINE +ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; + lit_utf8_size_t string1_size_and_length[2], string2_size_and_length[2]; + + utf8_string1_p = ecma_compare_get_string_chars (string1_p, string1_size_and_length); + utf8_string2_p = ecma_compare_get_string_chars (string2_p, string2_size_and_length); + + if (utf8_string1_p == NULL || utf8_string2_p == NULL) + { + return false; + } + + if (string1_size_and_length[0] != string2_size_and_length[0] + || string1_size_and_length[1] != string2_size_and_length[1]) + { + return false; + } + + return !memcmp ((char *) utf8_string1_p, (char *) utf8_string2_p, string1_size_and_length[0]); +} /* ecma_compare_ecma_strings_longpath */ + +/** + * Compare two ecma-strings + * + * @return true - if strings are equal; + * false - otherwise + */ +bool +ecma_compare_ecma_strings (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); + + /* Fast paths first. */ + if (string1_p == string2_p) + { + return true; + } + + /* Either string is direct, return with false. */ + if (ECMA_IS_DIRECT_STRING (((uintptr_t) string1_p) | ((uintptr_t) string2_p))) + { + return false; + } + + /* Also compares uint32 values in descriptor. */ + if (string1_p->u.hash != string2_p->u.hash) + { + return false; + } + + if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC; + } + + return ecma_compare_ecma_strings_longpath (string1_p, string2_p); +} /* ecma_compare_ecma_strings */ + +/** + * Compare two non-direct ecma-strings + * + * @return true - if strings are equal; + * false - otherwise + */ +bool +ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p) && !ECMA_IS_DIRECT_STRING (string2_p)); + + /* Fast paths first. */ + if (string1_p == string2_p) + { + return true; + } + + if (string1_p->u.hash != string2_p->u.hash) + { + return false; + } + + if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC; + } + + return ecma_compare_ecma_strings_longpath (string1_p, string2_p); +} /* ecma_compare_ecma_non_direct_strings */ + +/** + * Relational compare of ecma-strings. + * + * First string is less than second string if: + * - strings are not equal; + * - first string is prefix of second or is lexicographically less than second. + * + * @return true - if first string is less than second string, + * false - otherwise + */ +bool +ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + if (ecma_compare_ecma_strings (string1_p, string2_p)) + { + return false; + } + + const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; + lit_utf8_size_t utf8_string1_size, utf8_string2_size; + + lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + + if (ECMA_IS_DIRECT_STRING (string1_p)) + { + if (ECMA_GET_DIRECT_STRING_TYPE (string1_p) != ECMA_DIRECT_STRING_UINT) + { + utf8_string1_p = ecma_string_get_chars_fast (string1_p, &utf8_string1_size); + } + else + { + utf8_string1_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p), + uint32_to_string_buffer1, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string1_p = uint32_to_string_buffer1; + } + } + else + { + JERRY_ASSERT (string1_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string1_p) != ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + utf8_string1_p = ecma_string_get_chars_fast (string1_p, &utf8_string1_size); + } + else + { + utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, + uint32_to_string_buffer1, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string1_p = uint32_to_string_buffer1; + } + } + + if (ECMA_IS_DIRECT_STRING (string2_p)) + { + if (ECMA_GET_DIRECT_STRING_TYPE (string2_p) != ECMA_DIRECT_STRING_UINT) + { + utf8_string2_p = ecma_string_get_chars_fast (string2_p, &utf8_string2_size); + } + else + { + utf8_string2_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p), + uint32_to_string_buffer2, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string2_p = uint32_to_string_buffer2; + } + } + else + { + JERRY_ASSERT (string2_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string2_p) != ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + utf8_string2_p = ecma_string_get_chars_fast (string2_p, &utf8_string2_size); + } + else + { + utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, + uint32_to_string_buffer2, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string2_p = uint32_to_string_buffer2; + } + } + + return lit_compare_utf8_strings_relational (utf8_string1_p, utf8_string1_size, utf8_string2_p, utf8_string2_size); +} /* ecma_compare_ecma_strings_relational */ + +/** + * Special value to represent that no size is available. + */ +#define ECMA_STRING_NO_ASCII_SIZE 0xffffffff + +/** + * Return the size of uint32 and magic strings. + * The length of these strings are equal to their size. + * + * @return number of characters in the string + */ +static lit_utf8_size_t +ecma_string_get_ascii_size (const ecma_string_t *string_p) /**< ecma-string */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id >= LIT_MAGIC_STRING__COUNT) + { + return ECMA_STRING_NO_ASCII_SIZE; + } + + JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_utf8 (id), lit_get_magic_string_size (id))); + + return lit_get_magic_string_size (id); + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return ecma_string_get_uint32_size (uint32_number); + } + } + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ecma_string_get_uint32_size (string_p->u.uint32_number); + } + else if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_ASCII_STRING) + { + return ECMA_ASCII_STRING_GET_SIZE (string_p); + } + + return ECMA_STRING_NO_ASCII_SIZE; +} /* ecma_string_get_ascii_size */ + +/** + * Get length of ecma-string + * + * @return number of characters in the string + */ +lit_utf8_size_t +ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT; + return lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + return ((ecma_short_string_t *) string_p)->length; + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + return ((ecma_long_string_t *) string_p)->length; + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + return lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); +} /* ecma_string_get_length */ + +/** + * Get length of UTF-8 encoded string length from ecma-string + * + * @return number of characters in the UTF-8 encoded string + */ +lit_utf8_size_t +ecma_string_get_utf8_length (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT; + return lit_get_utf8_length_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + lit_utf8_size_t size = short_string_p->size; + + if (size == short_string_p->length) + { + return size; + } + + return lit_get_utf8_length_of_cesu8_string (ECMA_SHORT_STRING_GET_BUFFER (string_p), size); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + lit_utf8_size_t size = long_string_p->size; + + if (size == long_string_p->length) + { + return size; + } + + return lit_get_utf8_length_of_cesu8_string (long_string_p->string_p, size); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + + return lit_get_utf8_length_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); +} /* ecma_string_get_utf8_length */ + +/** + * Get size of ecma-string + * + * @return number of bytes in the buffer needed to represent the string + */ +lit_utf8_size_t +ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + return lit_get_magic_string_ex_size ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + return ((ecma_short_string_t *) string_p)->size; + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + return ((ecma_long_string_t *) string_p)->size; + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + return lit_get_magic_string_ex_size (LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id); +} /* ecma_string_get_size */ + +/** + * Get the UTF-8 encoded string size from ecma-string + * + * @return number of bytes in the buffer needed to represent an UTF-8 encoded string + */ +lit_utf8_size_t +ecma_string_get_utf8_size (const ecma_string_t *string_p) /**< ecma-string */ +{ + lit_utf8_size_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC); + JERRY_ASSERT ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) >= LIT_MAGIC_STRING__COUNT); + + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT; + return lit_get_utf8_size_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + lit_utf8_size_t size = short_string_p->size; + + if (size == short_string_p->length) + { + return size; + } + + return lit_get_utf8_size_of_cesu8_string (ECMA_SHORT_STRING_GET_BUFFER (string_p), size); + } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING) + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + + if (long_string_p->size == long_string_p->length) + { + return long_string_p->size; + } + + return lit_get_utf8_size_of_cesu8_string (long_string_p->string_p, long_string_p->size); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + return lit_get_utf8_size_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), lit_get_magic_string_ex_size (id)); +} /* ecma_string_get_utf8_size */ + +/** + * Get character from specified position in an external ecma-string. + * + * @return character value + */ +static ecma_char_t JERRY_ATTR_NOINLINE +ecma_external_string_get_char_at_pos (lit_utf8_size_t id, /**< id of the external magic string */ + lit_utf8_size_t index) /**< index of character */ +{ + id -= LIT_MAGIC_STRING__COUNT; + const lit_utf8_byte_t *data_p = lit_get_magic_string_ex_utf8 (id); + lit_utf8_size_t size = lit_get_magic_string_ex_size (id); + lit_utf8_size_t length = lit_utf8_string_length (data_p, size); + + if (JERRY_LIKELY (size == length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); +} /* ecma_external_string_get_char_at_pos */ + +/** + * Get character from specified position in the ecma-string. + * + * @return character value + */ +ecma_char_t +ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t index) /**< index of character */ +{ + JERRY_ASSERT (index < ecma_string_get_length (string_p)); + + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (JERRY_LIKELY (id < LIT_MAGIC_STRING__COUNT)) + { + /* All magic strings must be ascii strings. */ + const lit_utf8_byte_t *data_p = lit_get_magic_string_utf8 (id); + + return (ecma_char_t) data_p[index]; + } + + return ecma_external_string_get_char_at_pos (id, index); + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + ecma_uint32_to_utf8_string (uint32_number, uint32_to_string_buffer, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + return (ecma_char_t) uint32_to_string_buffer[index]; + } + } + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) string_p; + lit_utf8_size_t size = short_string_p->size; + const lit_utf8_byte_t *data_p = ECMA_SHORT_STRING_GET_BUFFER (string_p); + + if (JERRY_LIKELY (size == short_string_p->length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); + } + case ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING: + { + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + lit_utf8_size_t size = long_string_p->size; + const lit_utf8_byte_t *data_p = long_string_p->string_p; + + if (JERRY_LIKELY (size == long_string_p->length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + const lit_utf8_byte_t *data_p = ECMA_ASCII_STRING_GET_BUFFER (string_p); + return (ecma_char_t) data_p[index]; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + ecma_uint32_to_utf8_string (string_p->u.uint32_number, + uint32_to_string_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + return (ecma_char_t) uint32_to_string_buffer[index]; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + return ecma_external_string_get_char_at_pos (string_p->u.magic_string_ex_id, index); + } + } +} /* ecma_string_get_char_at_pos */ + +/** + * Check if passed string equals to one of magic strings + * and if equal magic string was found, return it's id in 'out_id_p' argument. + * + * @return id - if magic string equal to passed string was found, + * LIT_MAGIC_STRING__COUNT - otherwise. + */ +lit_magic_string_id_t +ecma_get_string_magic (const ecma_string_t *string_p) /**< ecma-string */ +{ + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_MAGIC)) + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (id < LIT_MAGIC_STRING__COUNT) + { + return (lit_magic_string_id_t) id; + } + } + + return LIT_MAGIC_STRING__COUNT; +} /* ecma_get_string_magic */ + +/** + * Try to calculate hash of the ecma-string + * + * @return calculated hash + */ +lit_string_hash_t +ecma_string_hash (const ecma_string_t *string_p) /**< ecma-string to calculate hash for */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return (lit_string_hash_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + } + + return (lit_string_hash_t) string_p->u.hash; +} /* ecma_string_hash */ + +/** + * Create a substring from an ecma string + * + * @return a newly consturcted ecma string with its value initialized to a copy of a substring of the first argument + */ +ecma_string_t * +ecma_string_substr (const ecma_string_t *string_p, /**< pointer to an ecma string */ + lit_utf8_size_t start_pos, /**< start position, should be less or equal than string length */ + lit_utf8_size_t end_pos) /**< end position, should be less or equal than string length */ +{ + const lit_utf8_size_t string_length = ecma_string_get_length (string_p); + JERRY_ASSERT (start_pos <= string_length); + JERRY_ASSERT (end_pos <= string_length); + + if (start_pos >= end_pos) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *ecma_string_p = NULL; + end_pos -= start_pos; + + ECMA_STRING_TO_UTF8_STRING (string_p, start_p, buffer_size); + + if (string_length == buffer_size) + { + ecma_string_p = ecma_new_ecma_string_from_utf8 (start_p + start_pos, (lit_utf8_size_t) end_pos); + } + else + { + while (start_pos--) + { + start_p += lit_get_unicode_char_size_by_utf8_first_byte (*start_p); + } + + const lit_utf8_byte_t *end_p = start_p; + while (end_pos--) + { + end_p += lit_get_unicode_char_size_by_utf8_first_byte (*end_p); + } + + ecma_string_p = ecma_new_ecma_string_from_utf8 (start_p, (lit_utf8_size_t) (end_p - start_p)); + } + + ECMA_FINALIZE_UTF8_STRING (start_p, buffer_size); + + return ecma_string_p; +} /* ecma_string_substr */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim_helper + * - ecma_builtin_global_object_parse_int + * - ecma_builtin_global_object_parse_float + * + * @return position of the first non whitespace character. + */ +const lit_utf8_byte_t * +ecma_string_trim_front (const lit_utf8_byte_t *start_p, /**< current string's start position */ + const lit_utf8_byte_t *end_p) /**< current string's end position */ +{ + ecma_char_t ch; + + while (start_p < end_p) + { + lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (start_p, &ch); + + if (!lit_char_is_white_space (ch)) + { + break; + } + + start_p += read_size; + } + + return start_p; +} /* ecma_string_trim_front */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim_helper + * + * @return position of the last non whitespace character. + */ +const lit_utf8_byte_t * +ecma_string_trim_back (const lit_utf8_byte_t *start_p, /**< current string's start position */ + const lit_utf8_byte_t *end_p) /**< current string's end position */ +{ + ecma_char_t ch; + + while (end_p > start_p) + { + lit_utf8_size_t read_size = lit_read_prev_code_unit_from_utf8 (end_p, &ch); + + if (!lit_char_is_white_space (ch)) + { + break; + } + + end_p -= read_size; + } + + return end_p; +} /* ecma_string_trim_back */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim + * - ecma_utf8_string_to_number + * + * @return void + */ +void +ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p, /**< [in, out] current string position */ + lit_utf8_size_t *utf8_str_size) /**< [in, out] size of the given string */ +{ + const lit_utf8_byte_t *end_p = *utf8_str_p + *utf8_str_size; + const lit_utf8_byte_t *start_p = *utf8_str_p; + + const lit_utf8_byte_t *new_start_p = ecma_string_trim_front (start_p, end_p); + const lit_utf8_byte_t *new_end_p = ecma_string_trim_back (new_start_p, end_p); + + *utf8_str_size = (lit_utf8_size_t) (new_end_p - new_start_p); + *utf8_str_p = new_start_p; +} /* ecma_string_trim_helper */ + +/** + * Trim leading and trailing whitespace characters from string. + * + * @return trimmed ecma string + */ +ecma_string_t * +ecma_string_trim (const ecma_string_t *string_p) /**< pointer to an ecma string */ +{ + ecma_string_t *ret_string_p; + + lit_utf8_size_t utf8_str_size; + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; + const lit_utf8_byte_t *utf8_str_p = ecma_string_get_chars (string_p, &utf8_str_size, NULL, NULL, &flags); + + if (utf8_str_size > 0) + { + ecma_string_trim_helper (&utf8_str_p, &utf8_str_size); + ret_string_p = ecma_new_ecma_string_from_utf8 (utf8_str_p, utf8_str_size); + } + else + { + ret_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + if (flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) utf8_str_p, utf8_str_size); + } + + return ret_string_p; +} /* ecma_string_trim */ + +/** + * Pad the beginning or the end of string with parameter given in fill_string to the length of max_length. + * + * @return new string from original, padded with given parameters + */ +ecma_value_t +ecma_string_pad (ecma_value_t original_string_p, /**< Input ecma string */ + ecma_value_t max_length, /**< Length to pad to, including original length */ + ecma_value_t fill_string, /**< The string to pad with */ + bool pad_on_start) /**< true - if we are padding to the start, calling with padStart + false - if we are padding to the end, calling with padEnd */ +{ + /* 3 */ + ecma_length_t int_max_length; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_length (max_length, &int_max_length))) + { + return ECMA_VALUE_ERROR; + } + /* 4 */ + ecma_string_t *original_str_val_p = ecma_get_string_from_value (original_string_p); + const uint32_t string_length = ecma_string_get_length (original_str_val_p); + /* 5 */ + if (int_max_length <= string_length) + { + ecma_ref_ecma_string (original_str_val_p); + return original_string_p; + } + + ecma_string_t *filler_p = ecma_get_magic_string (LIT_MAGIC_STRING_SPACE_CHAR); + /* 6 - 7 */ + if (!ecma_is_value_undefined (fill_string)) + { + filler_p = ecma_op_to_string (fill_string); + if (filler_p == NULL) + { + return ECMA_VALUE_ERROR; + } + if (ecma_string_is_empty (filler_p)) + { + ecma_ref_ecma_string (original_str_val_p); + return original_string_p; + } + } + + if (int_max_length >= UINT32_MAX) + { + ecma_deref_ecma_string (filler_p); + return ecma_raise_range_error (ECMA_ERR_MAXIMUM_STRING_LENGTH_IS_REACHED); + } + + /* 9 */ + uint32_t fill_len = (uint32_t) int_max_length - string_length; + + /* 10 */ + uint32_t filler_length = ecma_string_get_length (filler_p); + uint32_t prepend_count = fill_len / filler_length; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (!pad_on_start) + { + ecma_stringbuilder_append (&builder, original_str_val_p); + } + + for (uint32_t i = 0; i < prepend_count; i++) + { + ecma_stringbuilder_append (&builder, filler_p); + } + + uint32_t remaining = fill_len - (prepend_count * filler_length); + + ECMA_STRING_TO_UTF8_STRING (filler_p, start_p, utf8_str_size); + const lit_utf8_byte_t *temp_start_p = start_p; + while (remaining > 0) + { + ecma_char_t ch; + lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (temp_start_p, &ch); + ecma_stringbuilder_append_char (&builder, ch); + temp_start_p += read_size; + remaining--; + } + ECMA_FINALIZE_UTF8_STRING (start_p, utf8_str_size); + ecma_deref_ecma_string (filler_p); + + /* 11 - 12 */ + if (pad_on_start) + { + ecma_stringbuilder_append (&builder, original_str_val_p); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_string_pad */ + +/** + * Create an empty string builder + * + * @return new string builder + */ +ecma_stringbuilder_t +ecma_stringbuilder_create (void) +{ + const lit_utf8_size_t initial_size = ECMA_ASCII_STRING_HEADER_SIZE; + ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); + header_p->current_size = initial_size; + + ecma_stringbuilder_t ret = { header_p }; + return ret; +} /* ecma_stringbuilder_create */ + +/** + * Create a string builder from an ecma string + * + * @return new string builder + */ +ecma_stringbuilder_t +ecma_stringbuilder_create_from (ecma_string_t *string_p) /**< ecma string */ +{ + const lit_utf8_size_t string_size = ecma_string_get_size (string_p); + const lit_utf8_size_t initial_size = string_size + ECMA_ASCII_STRING_HEADER_SIZE; + + ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); + header_p->current_size = initial_size; + + ecma_string_to_cesu8_bytes (string_p, ECMA_STRINGBUILDER_STRING_PTR (header_p), string_size); + + ecma_stringbuilder_t ret = { header_p }; + return ret; +} /* ecma_stringbuilder_create_from */ + +/** + * Create a string builder from a raw string + * + * @return new string builder + */ +ecma_stringbuilder_t +ecma_stringbuilder_create_raw (const lit_utf8_byte_t *data_p, /**< pointer to data */ + const lit_utf8_size_t data_size) /**< size of the data */ +{ + const lit_utf8_size_t initial_size = data_size + ECMA_ASCII_STRING_HEADER_SIZE; + + ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); + header_p->current_size = initial_size; + + memcpy (ECMA_STRINGBUILDER_STRING_PTR (header_p), data_p, data_size); + + ecma_stringbuilder_t ret = { header_p }; + return ret; +} /* ecma_stringbuilder_create_raw */ + +/** + * Grow the underlying buffer of a string builder + * + * @return pointer to the end of the data in the underlying buffer + */ +static lit_utf8_byte_t * +ecma_stringbuilder_grow (ecma_stringbuilder_t *builder_p, /**< string builder */ + lit_utf8_size_t required_size) /**< required size */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + const lit_utf8_size_t new_size = header_p->current_size + required_size; + header_p = (ecma_stringbuilder_header_t *) jmem_heap_realloc_block (header_p, header_p->current_size, new_size); + header_p->current_size = new_size; + builder_p->header_p = header_p; + + return ((lit_utf8_byte_t *) header_p) + header_p->current_size - required_size; +} /* ecma_stringbuilder_grow */ + +/** + * Get the current size of the string in a string builder + * + * @return the size of the string data + */ +lit_utf8_size_t +ecma_stringbuilder_get_size (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + return ECMA_STRINGBUILDER_STRING_SIZE (header_p); +} /* ecma_stringbuilder_get_size */ + +/** + * Get pointer to the raw string data in a string builder + * + * @return pointer to the string data + */ +lit_utf8_byte_t * +ecma_stringbuilder_get_data (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + return ECMA_STRINGBUILDER_STRING_PTR (header_p); +} /* ecma_stringbuilder_get_data */ + +/** + * Revert the string builder to a smaller size + */ +void +ecma_stringbuilder_revert (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_utf8_size_t size) /**< new size */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + const lit_utf8_size_t new_size = size + ECMA_ASCII_STRING_HEADER_SIZE; + JERRY_ASSERT (new_size <= header_p->current_size); + + header_p = (ecma_stringbuilder_header_t *) jmem_heap_realloc_block (header_p, header_p->current_size, new_size); + header_p->current_size = new_size; + builder_p->header_p = header_p; +} /* ecma_stringbuilder_revert */ + +/** + * Append an ecma_string_t to a string builder + */ +void +ecma_stringbuilder_append (ecma_stringbuilder_t *builder_p, /**< string builder */ + const ecma_string_t *string_p) /**< ecma string */ +{ + const lit_utf8_size_t string_size = ecma_string_get_size (string_p); + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, string_size); + + ecma_string_to_cesu8_bytes (string_p, dest_p, string_size); +} /* ecma_stringbuilder_append */ + +/** + * Append a magic string to a string builder + */ +void +ecma_stringbuilder_append_magic (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_magic_string_id_t id) /**< magic string id */ +{ + const lit_utf8_size_t string_size = lit_get_magic_string_size (id); + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, string_size); + + const lit_utf8_byte_t *string_data_p = lit_get_magic_string_utf8 (id); + memcpy (dest_p, string_data_p, string_size); +} /* ecma_stringbuilder_append_magic */ + +/** + * Append raw string data to a string builder + */ +void +ecma_stringbuilder_append_raw (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_utf8_byte_t *data_p, /**< pointer to data */ + const lit_utf8_size_t data_size) /**< size of the data */ +{ + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, data_size); + memcpy (dest_p, data_p, data_size); +} /* ecma_stringbuilder_append_raw */ + +/** + * Append a codepoint to a string builder + */ +void +ecma_stringbuilder_append_codepoint (ecma_stringbuilder_t *builder_p, /**< string builder */ + lit_code_point_t cp) /**< code point */ +{ + const lit_utf8_size_t size = (lit_utf8_size_t) lit_code_point_get_cesu8_length (cp); + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, size); + + lit_code_point_to_cesu8_bytes (dest_p, cp); +} /* ecma_stringbuilder_append_codepoint */ + +/** + * Append an ecma_char_t to a string builder + */ +void +ecma_stringbuilder_append_char (ecma_stringbuilder_t *builder_p, /**< string builder */ + const ecma_char_t c) /**< ecma char */ +{ + ecma_stringbuilder_append_codepoint (builder_p, c); +} /* ecma_stringbuilder_append_char */ + +/** + * Append a single byte to a string builder + */ +void +ecma_stringbuilder_append_byte (ecma_stringbuilder_t *builder_p, /**< string builder */ + const lit_utf8_byte_t byte) /**< byte */ +{ + lit_utf8_byte_t *dest_p = ecma_stringbuilder_grow (builder_p, 1); + *dest_p = byte; +} /* ecma_stringbuilder_append_byte */ + +/** + * Finalize a string builder, returning the created string, and releasing the underlying buffer. + * + * Note: + * The builder should no longer be used. + * + * @return the created string + */ +ecma_string_t * +ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + ecma_stringbuilder_header_t *header_p = builder_p->header_p; + JERRY_ASSERT (header_p != NULL); + + const lit_utf8_size_t string_size = ECMA_STRINGBUILDER_STRING_SIZE (header_p); + lit_utf8_byte_t *string_begin_p = ECMA_STRINGBUILDER_STRING_PTR (header_p); + + ecma_string_t *string_p = ecma_find_special_string (string_begin_p, string_size); + + if (JERRY_UNLIKELY (string_p != NULL)) + { + ecma_stringbuilder_destroy (builder_p); + return string_p; + } + +#ifndef JERRY_NDEBUG + builder_p->header_p = NULL; +#endif /* !defined (JERRY_NDEBUG) */ + + size_t container_size = sizeof (ecma_short_string_t); + const lit_string_hash_t hash = lit_utf8_string_calc_hash (string_begin_p, string_size); + const lit_utf8_size_t length = lit_utf8_string_length (string_begin_p, string_size); + + if (JERRY_LIKELY (string_size <= UINT16_MAX)) + { + if (JERRY_LIKELY (length == string_size) && string_size <= (UINT8_MAX + 1)) + { + string_p = (ecma_string_t *) header_p; + string_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_ASCII_STRING | ECMA_STRING_REF_ONE; + string_p->u.hash = hash; + ECMA_ASCII_STRING_SET_SIZE (string_p, string_size); + + return (ecma_string_t *) string_p; + } + } + else + { + container_size = sizeof (ecma_long_string_t); + } + + const size_t utf8_string_size = string_size + container_size; + header_p = (ecma_stringbuilder_header_t *) jmem_heap_realloc_block (header_p, header_p->current_size, utf8_string_size); + memmove (((lit_utf8_byte_t *) header_p + container_size), ECMA_STRINGBUILDER_STRING_PTR (header_p), string_size); + + if (JERRY_LIKELY (string_size <= UINT16_MAX)) + { + ecma_short_string_t *short_string_p = (ecma_short_string_t *) header_p; + + short_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; + short_string_p->header.u.hash = hash; + short_string_p->size = (uint16_t) string_size; + short_string_p->length = (uint16_t) length; + + return (ecma_string_t *) short_string_p; + } + + ecma_long_string_t *long_string_p = (ecma_long_string_t *) header_p; + + long_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING | ECMA_STRING_REF_ONE; + long_string_p->header.u.hash = hash; + long_string_p->string_p = ECMA_LONG_STRING_BUFFER_START (long_string_p); + long_string_p->size = string_size; + long_string_p->length = length; + + return (ecma_string_t *) long_string_p; +} /* ecma_stringbuilder_finalize */ + +/** + * Destroy a string builder that is no longer needed without creating a string from the contents. + */ +void +ecma_stringbuilder_destroy (ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + JERRY_ASSERT (builder_p->header_p != NULL); + const lit_utf8_size_t size = builder_p->header_p->current_size; + jmem_heap_free_block (builder_p->header_p, size); + +#ifndef JERRY_NDEBUG + builder_p->header_p = NULL; +#endif /* !defined (JERRY_NDEBUG) */ + +} /* ecma_stringbuilder_destroy */ + +/** + * AdvanceStringIndex operation + * + * See also: + * ECMA-262 v6.0, 21.2.5.2.3 + * + * @return uint32_t - the proper character index based on the operation + */ +ecma_length_t +ecma_op_advance_string_index (ecma_string_t *str_p, /**< input string */ + ecma_length_t index, /**< given character index */ + bool is_unicode) /**< true - if regexp object's "unicode" flag is set + false - otherwise */ +{ + JERRY_ASSERT ((ecma_number_t) index <= ECMA_NUMBER_MAX_SAFE_INTEGER); + ecma_length_t next_index = index + 1; + + if (!is_unicode) + { + return next_index; + } + + lit_utf8_size_t str_len = ecma_string_get_length (str_p); + + if (next_index >= str_len) + { + return next_index; + } + + JERRY_ASSERT (index < UINT32_MAX); + ecma_char_t first = ecma_string_get_char_at_pos (str_p, (lit_utf8_size_t) index); + + if (!lit_is_code_point_utf16_high_surrogate (first)) + { + return next_index; + } + + ecma_char_t second = ecma_string_get_char_at_pos (str_p, (lit_utf8_size_t) next_index); + + if (!lit_is_code_point_utf16_low_surrogate (second)) + { + return next_index; + } + + return next_index + 1; +} /* ecma_op_advance_string_index */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-value.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-value.cpp new file mode 100644 index 00000000..cf7826b9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers-value.cpp @@ -0,0 +1,1257 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" + +#include "jrt-bit-fields.h" +#include "jrt.h" +#include "vm-defines.h" + +JERRY_STATIC_ASSERT (((int)ECMA_TYPE___MAX <= (int)ECMA_VALUE_TYPE_MASK), ecma_types_must_be_less_than_mask); + +JERRY_STATIC_ASSERT (((ECMA_VALUE_TYPE_MASK + 1) == (1 << ECMA_VALUE_SHIFT)), ecma_value_part_must_start_after_flags); + +JERRY_STATIC_ASSERT (((int)ECMA_VALUE_SHIFT <= (int)JMEM_ALIGNMENT_LOG), + ecma_value_shift_must_be_less_than_or_equal_than_mem_alignment_log); + +JERRY_STATIC_ASSERT ((sizeof (jmem_cpointer_t) <= sizeof (ecma_value_t)), + size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_ecma_value_t); + +JERRY_STATIC_ASSERT ((sizeof (jmem_cpointer_t) <= sizeof (jmem_cpointer_tag_t)), + size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_jmem_cpointer_tag_t); + +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + +/* cppcheck-suppress zerodiv */ +JERRY_STATIC_ASSERT (sizeof (uintptr_t) <= sizeof (ecma_value_t), uintptr_t_must_fit_in_ecma_value_t); + +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +JERRY_STATIC_ASSERT ((sizeof (uintptr_t) > sizeof (ecma_value_t)), uintptr_t_must_not_fit_in_ecma_value_t); + +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +JERRY_STATIC_ASSERT ((((int)ECMA_VALUE_FALSE | (1 << (int)ECMA_DIRECT_SHIFT)) == (int)ECMA_VALUE_TRUE) + && ECMA_VALUE_FALSE != ECMA_VALUE_TRUE, + only_the_lowest_bit_must_be_different_for_simple_value_true_and_false); + +#if JERRY_BUILTIN_BIGINT + +JERRY_STATIC_ASSERT (ECMA_NULL_POINTER == (ECMA_BIGINT_ZERO & ~(ecma_value_t) ECMA_VALUE_TYPE_MASK), + ecma_bigint_zero_must_be_encoded_as_null_pointer); + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Get type field of ecma value + * + * @return type field + */ +ecma_type_t JERRY_ATTR_CONST +ecma_get_value_type_field (ecma_value_t value) /**< ecma value */ +{ + return (ecma_type_t)(((unsigned int) value) & ((unsigned int)ECMA_VALUE_TYPE_MASK)); +} /* ecma_get_value_type_field */ + +/** + * Convert a pointer into an ecma value. + * + * @return ecma value + */ +static inline ecma_value_t JERRY_ATTR_PURE +ecma_pointer_to_ecma_value (const void *ptr) /**< pointer */ +{ +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + + JERRY_ASSERT (ptr != NULL); + uintptr_t uint_ptr = (uintptr_t) ptr; + JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0); + return (ecma_value_t) uint_ptr; + +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + + jmem_cpointer_t ptr_cp; + ECMA_SET_NON_NULL_POINTER (ptr_cp, ptr); + return ((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT; + +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +} /* ecma_pointer_to_ecma_value */ + +/** + * Get a pointer from an ecma value + * + * @return pointer + */ +static inline void *JERRY_ATTR_PURE +ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */ +{ +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + void *ptr = (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK); + JERRY_ASSERT (ptr != NULL); + return ptr; +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + return ECMA_GET_NON_NULL_POINTER (void, value >> ECMA_VALUE_SHIFT); +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +} /* ecma_get_pointer_from_ecma_value */ + +/** + * Check if the value is direct ecma-value. + * + * @return true - if the value is a direct value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_direct (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT); +} /* ecma_is_value_direct */ + +/** + * Check if the value is simple ecma-value. + * + * @return true - if the value is a simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_simple (ecma_value_t value) /**< ecma value */ +{ + return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_SIMPLE_VALUE; +} /* ecma_is_value_simple */ + +/** + * Check whether the value is a given simple value. + * + * @return true - if the value is equal to the given simple value, + * false - otherwise + */ +static inline bool JERRY_ATTR_CONST +ecma_is_value_equal_to_simple_value (ecma_value_t value, /**< ecma value */ + ecma_value_t simple_value) /**< simple value */ +{ + return value == simple_value; +} /* ecma_is_value_equal_to_simple_value */ + +/** + * Check if the value is empty. + * + * @return true - if the value contains implementation-defined empty simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_empty (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_EMPTY); +} /* ecma_is_value_empty */ + +/** + * Check if the value is undefined. + * + * @return true - if the value contains ecma-undefined simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_undefined (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_UNDEFINED); +} /* ecma_is_value_undefined */ + +/** + * Check if the value is null. + * + * @return true - if the value contains ecma-null simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_null (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_NULL); +} /* ecma_is_value_null */ + +/** + * Check if the value is boolean. + * + * @return true - if the value contains ecma-true or ecma-false simple values, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_boolean (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_true (value | (1 << ECMA_DIRECT_SHIFT)); +} /* ecma_is_value_boolean */ + +/** + * Check if the value is true. + * + * @return true - if the value contains ecma-true simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_true (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_TRUE); +} /* ecma_is_value_true */ + +/** + * Check if the value is false. + * + * @return true - if the value contains ecma-false simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_false (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_FALSE); +} /* ecma_is_value_false */ + +/** + * Check if the value is not found. + * + * @return true - if the value contains ecma-not-found simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_found (ecma_value_t value) /**< ecma value */ +{ + return value != ECMA_VALUE_NOT_FOUND; +} /* ecma_is_value_found */ + +/** + * Check if the value is array hole. + * + * @return true - if the value contains ecma-array-hole simple value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_array_hole (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_ARRAY_HOLE); +} /* ecma_is_value_array_hole */ + +/** + * Check if the value is integer ecma-number. + * + * @return true - if the value contains an integer ecma-number value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_integer_number (ecma_value_t value) /**< ecma value */ +{ + return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE; +} /* ecma_is_value_integer_number */ + +/** + * Check if both values are integer ecma-numbers. + * + * @return true - if both values contain integer ecma-number values, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_are_values_integer_numbers (ecma_value_t first_value, /**< first ecma value */ + ecma_value_t second_value) /**< second ecma value */ +{ + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0, ecma_direct_type_integer_value_must_be_zero); + + return ((first_value | second_value) & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE; +} /* ecma_are_values_integer_numbers */ + +/** + * Check if the value is floating-point ecma-number. + * + * @return true - if the value contains a floating-point ecma-number value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_float_number (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT); +} /* ecma_is_value_float_number */ + +/** + * Check if the value is ecma-number. + * + * @return true - if the value contains ecma-number value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_number (ecma_value_t value) /**< ecma value */ +{ + return (ecma_is_value_integer_number (value) || ecma_is_value_float_number (value)); +} /* ecma_is_value_number */ + +JERRY_STATIC_ASSERT (((ECMA_TYPE_STRING | 0x4) == ECMA_TYPE_DIRECT_STRING), + ecma_type_string_and_direct_string_must_have_one_bit_difference); + +/** + * Check if the value is ecma-string. + * + * @return true - if the value contains ecma-string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_string (ecma_value_t value) /**< ecma value */ +{ + return ((value & (ECMA_VALUE_TYPE_MASK - 0x4)) == ECMA_TYPE_STRING); +} /* ecma_is_value_string */ + +/** + * Check if the value is symbol. + * + * @return true - if the value contains symbol value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_symbol (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_SYMBOL); +} /* ecma_is_value_symbol */ + +/** + * Check if the value is a specific magic string. + * + * @return true - if the value the magic string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_magic_string (ecma_value_t value, /**< ecma value */ + lit_magic_string_id_t id) /**< magic string id */ +{ + return value == ecma_make_magic_string_value (id); +} /* ecma_is_value_magic_string */ + +/** + * Check if the value is bigint. + * + * @return true - if the value contains bigint value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_bigint (ecma_value_t value) /**< ecma value */ +{ +#if JERRY_BUILTIN_BIGINT + return (ecma_get_value_type_field (value) == ECMA_TYPE_BIGINT); +#else /* !JERRY_BUILTIN_BIGINT */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* ecma_is_value_bigint */ + +/** + * Check if the value can be property name. + * + * @return true - if the value can be property name value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_prop_name (ecma_value_t value) /**< ecma value */ +{ + return ecma_is_value_string (value) || ecma_is_value_symbol (value); +} /* ecma_is_value_prop_name */ + +/** + * Check if the value is direct ecma-string. + * + * @return true - if the value contains direct ecma-string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_direct_string (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING); +} /* ecma_is_value_direct_string */ + +/** + * Check if the value is non-direct ecma-string. + * + * @return true - if the value contains non-direct ecma-string value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_non_direct_string (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING); +} /* ecma_is_value_non_direct_string */ + +/** + * Check if the value is object. + * + * @return true - if the value contains object value, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_object (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT); +} /* ecma_is_value_object */ + +/** + * Check if the value is error reference. + * + * @return true - if the value contains an error reference, + * false - otherwise + */ +bool JERRY_ATTR_CONST +ecma_is_value_exception (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR); +} /* ecma_is_value_exception */ + +/** + * Debug assertion that specified value's type is one of ECMA-defined + * script-visible types, i.e.: undefined, null, boolean, number, string, object. + */ +void +ecma_check_value_type_is_spec_defined (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_undefined (value) || ecma_is_value_null (value) || ecma_is_value_boolean (value) + || ecma_is_value_number (value) || ecma_is_value_string (value) || ecma_is_value_bigint (value) + || ecma_is_value_symbol (value) || ecma_is_value_object (value)); +} /* ecma_check_value_type_is_spec_defined */ + +/** + * Checks if the given argument is an array or not. + * + * @return ECMA_VALUE_ERROR- if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether 'arg' is an array object + */ +ecma_value_t +ecma_is_value_array (ecma_value_t arg) /**< argument */ +{ + if (!ecma_is_value_object (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *arg_obj_p = ecma_get_object_from_value (arg); + + if (ecma_get_object_base_type (arg_obj_p) == ECMA_OBJECT_BASE_TYPE_ARRAY) + { + return ECMA_VALUE_TRUE; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (arg_obj_p)) + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) arg_obj_p; + + if (proxy_obj_p->handler == ECMA_VALUE_NULL) + { + return ecma_raise_type_error (ECMA_ERR_PROXY_HANDLER_IS_NULL_FOR_ISARRAY_OPERATION); + } + + return ecma_is_value_array (proxy_obj_p->target); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ECMA_VALUE_FALSE; +} /* ecma_is_value_array */ + +/** + * Creates an ecma value from the given raw boolean. + * + * @return boolean ecma_value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_make_boolean_value (bool boolean_value) /**< raw bool value from which the ecma value will be created */ +{ + return boolean_value ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE; +} /* ecma_make_boolean_value */ + +/** + * Encode an integer number into an ecma-value without allocating memory + * + * Note: + * The value must fit into the range of allowed ecma integer values + * + * @return ecma-value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_make_integer_value (ecma_integer_value_t integer_value) /**< integer number to be encoded */ +{ + JERRY_ASSERT (ECMA_IS_INTEGER_NUMBER (integer_value)); + + return (((ecma_value_t) integer_value) << ECMA_DIRECT_SHIFT) | ECMA_DIRECT_TYPE_INTEGER_VALUE; +} /* ecma_make_integer_value */ + +/** + * Allocate and initialize a new float number without checks. + * + * @return ecma-value + */ +static ecma_value_t +ecma_create_float_number (ecma_number_t ecma_number) /**< value of the float number */ +{ + ecma_number_t *ecma_num_p = ecma_alloc_number (); + + *ecma_num_p = ecma_number; + + return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT; +} /* ecma_create_float_number */ + +/** + * Encode float number without checks. + * + * @return ecma-value + */ +ecma_value_t +ecma_make_float_value (ecma_number_t *ecma_num_p) /**< pointer to the float number */ +{ + return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT; +} /* ecma_make_float_value */ + +/** + * Create a new NaN value. + * + * @return ecma-value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_make_nan_value (void) +{ + return ecma_create_float_number (ecma_number_make_nan ()); +} /* ecma_make_nan_value */ + +/** + * Checks whether the passed number is +0.0 + * + * @return true, if it is +0.0, false otherwise + */ +static inline bool JERRY_ATTR_CONST +ecma_is_number_equal_to_positive_zero (ecma_number_t ecma_number) /**< number */ +{ + return ecma_number_to_binary (ecma_number) == ECMA_NUMBER_BINARY_ZERO; +} /* ecma_is_number_equal_to_positive_zero */ + +/** + * Encode a property length number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_length_value (ecma_length_t number) /**< number to be encoded */ +{ + if (number <= ECMA_INTEGER_NUMBER_MAX) + { + return ecma_make_integer_value ((ecma_integer_value_t) number); + } + + return ecma_create_float_number ((ecma_number_t) number); +} /* ecma_make_length_value */ + +/** + * Encode a number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_number_value (ecma_number_t ecma_number) /**< number to be encoded */ +{ + ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number; + + if ((ecma_number_t) integer_value == ecma_number + && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number) + : ECMA_IS_INTEGER_NUMBER (integer_value))) + { + return ecma_make_integer_value (integer_value); + } + + return ecma_create_float_number (ecma_number); +} /* ecma_make_number_value */ + +/** + * Encode an int32 number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_int32_value (int32_t int32_number) /**< int32 number to be encoded */ +{ + if (ECMA_IS_INTEGER_NUMBER (int32_number)) + { + return ecma_make_integer_value ((ecma_integer_value_t) int32_number); + } + + return ecma_create_float_number ((ecma_number_t) int32_number); +} /* ecma_make_int32_value */ + +/** + * Encode an unsigned int32 number into an ecma-value + * + * @return ecma-value + */ +ecma_value_t +ecma_make_uint32_value (uint32_t uint32_number) /**< uint32 number to be encoded */ +{ + if (uint32_number <= ECMA_INTEGER_NUMBER_MAX) + { + return ecma_make_integer_value ((ecma_integer_value_t) uint32_number); + } + + return ecma_create_float_number ((ecma_number_t) uint32_number); +} /* ecma_make_uint32_value */ + +/** + * String value constructor + * + * @return ecma-value representation of the string argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */ +{ + JERRY_ASSERT (ecma_string_p != NULL); + JERRY_ASSERT (!ecma_prop_name_is_symbol ((ecma_string_t *) ecma_string_p)); + + if ((((uintptr_t) ecma_string_p) & ECMA_VALUE_TYPE_MASK) != 0) + { + return (ecma_value_t) (uintptr_t) ecma_string_p; + } + + return ecma_pointer_to_ecma_value (ecma_string_p) | ECMA_TYPE_STRING; +} /* ecma_make_string_value */ + +/** + * Symbol value constructor + * + * @return ecma-value representation of the string argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p) /**< symbol to reference in value */ +{ + JERRY_ASSERT (ecma_symbol_p != NULL); + JERRY_ASSERT (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_symbol_p)); + + return ecma_pointer_to_ecma_value (ecma_symbol_p) | ECMA_TYPE_SYMBOL; +} /* ecma_make_symbol_value */ + +/** + * Property-name value constructor + * + * @return ecma-value representation of a property name argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p) /**< property name to reference in value */ +{ + JERRY_ASSERT (ecma_prop_name_p != NULL); + + if (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_prop_name_p)) + { + return ecma_make_symbol_value (ecma_prop_name_p); + } + + return ecma_make_string_value (ecma_prop_name_p); +} /* ecma_make_prop_name_value */ + +/** + * String value constructor + * + * @return ecma-value representation of the string argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_magic_string_value (lit_magic_string_id_t id) /**< magic string id */ +{ + return (ecma_value_t) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, (uintptr_t) id); +} /* ecma_make_magic_string_value */ + +/** + * Object value constructor + * + * @return ecma-value representation of the object argument + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference in value */ +{ + JERRY_ASSERT (object_p != NULL); + + return ecma_pointer_to_ecma_value (object_p) | ECMA_TYPE_OBJECT; +} /* ecma_make_object_value */ + +/** + * Error reference constructor + * + * @return ecma-value representation of the Error reference + */ +ecma_value_t JERRY_ATTR_PURE +ecma_make_extended_primitive_value (const ecma_extended_primitive_t *primitve_p, /**< extended primitve value */ + uint32_t type) /**< ecma type of extended primitve value */ +{ + JERRY_ASSERT (primitve_p != NULL); +#if JERRY_BUILTIN_BIGINT + JERRY_ASSERT (primitve_p != ECMA_BIGINT_POINTER_TO_ZERO); +#endif /* JERRY_BUILTIN_BIGINT */ + JERRY_ASSERT (type == ECMA_TYPE_BIGINT || type == ECMA_TYPE_ERROR); + + return ecma_pointer_to_ecma_value (primitve_p) | type; +} /* ecma_make_extended_primitive_value */ + +/** + * Get integer value from an integer ecma value + * + * @return integer value + */ +ecma_integer_value_t JERRY_ATTR_CONST +ecma_get_integer_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_integer_number (value)); + + return ((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT; +} /* ecma_get_integer_from_value */ + +/** + * Get floating point value from an ecma value + * + * @return floating point value + */ +ecma_number_t JERRY_ATTR_PURE +ecma_get_float_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT); + + return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_float_from_value */ + +/** + * Get floating point value pointer from an ecma value + * + * @return floating point value + */ +ecma_number_t *JERRY_ATTR_PURE +ecma_get_pointer_from_float_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT); + + return (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_pointer_from_float_value */ + +/** + * Get floating point value from an ecma value + * + * @return floating point value + */ +ecma_number_t JERRY_ATTR_PURE +ecma_get_number_from_value (ecma_value_t value) /**< ecma value */ +{ + if (ecma_is_value_integer_number (value)) + { + return (ecma_number_t) ecma_get_integer_from_value (value); + } + + return ecma_get_float_from_value (value); +} /* ecma_get_number_from_value */ + +/** + * Get pointer to ecma-string from ecma value + * + * @return the string pointer + */ +ecma_string_t *JERRY_ATTR_PURE +ecma_get_string_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_string (value)); + + if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING) + { + return (ecma_string_t *) (uintptr_t) value; + } + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_string_from_value */ + +/** + * Get pointer to ecma-string from ecma value + * + * @return the string pointer + */ +ecma_string_t *JERRY_ATTR_PURE +ecma_get_symbol_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_symbol (value)); + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_symbol_from_value */ + +/** + * Get pointer to a property name from ecma value + * + * @return the string pointer + */ +ecma_string_t *JERRY_ATTR_PURE +ecma_get_prop_name_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_prop_name (value)); + + if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING) + { + return (ecma_string_t *) (uintptr_t) value; + } + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_prop_name_from_value */ + +/** + * Get pointer to ecma-object from ecma value + * + * @return the pointer + */ +ecma_object_t *JERRY_ATTR_PURE +ecma_get_object_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_object (value)); + + return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_object_from_value */ + +/** + * Get pointer to error reference from ecma value + * + * @return the pointer + */ +ecma_extended_primitive_t *JERRY_ATTR_PURE +ecma_get_extended_primitive_from_value (ecma_value_t value) /**< ecma value */ +{ +#if JERRY_BUILTIN_BIGINT + JERRY_ASSERT (value != ECMA_BIGINT_ZERO); +#endif /* JERRY_BUILTIN_BIGINT */ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_BIGINT + || ecma_get_value_type_field (value) == ECMA_TYPE_ERROR); + + return (ecma_extended_primitive_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_extended_primitive_from_value */ + +/** + * Invert a boolean value + * + * @return ecma value + */ +ecma_value_t JERRY_ATTR_CONST +ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_boolean (value)); + + return (value ^ (1 << ECMA_DIRECT_SHIFT)); +} /* ecma_invert_boolean_value */ + +/** + * Copy ecma value. + * + * @return copy of the given value + */ +ecma_value_t +ecma_copy_value (ecma_value_t value) /**< value description */ +{ + switch (ecma_get_value_type_field (value)) + { + case ECMA_TYPE_FLOAT: + { + ecma_number_t *num_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); + ecma_number_t *new_num_p = ecma_alloc_number (); + + *new_num_p = *num_p; + + return ecma_make_float_value (new_num_p); + } + case ECMA_TYPE_SYMBOL: + case ECMA_TYPE_STRING: + { + ecma_string_t *string_p = (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); + ecma_ref_ecma_string_non_direct (string_p); + return value; + } +#if JERRY_BUILTIN_BIGINT + case ECMA_TYPE_BIGINT: + { + if (value != ECMA_BIGINT_ZERO) + { + ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value)); + } + return value; + } +#endif /* JERRY_BUILTIN_BIGINT */ + case ECMA_TYPE_OBJECT: + { + ecma_ref_object_inline (ecma_get_object_from_value (value)); + return value; + } + default: + { + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT + || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING); + + return value; + } + } +} /* ecma_copy_value */ + +/** + * Copy ecma value. + * + * Note: + * this function is similar to ecma_copy_value, but it is + * faster for direct values since no function call is performed. + * It also increases the binary size so it is recommended for + * critical code paths only. + * + * @return copy of the given value + */ +ecma_value_t +ecma_fast_copy_value (ecma_value_t value) /**< value description */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT) ? value : ecma_copy_value (value); +} /* ecma_fast_copy_value */ + +/** + * Copy the ecma value if not an object + * + * @return copy of the given value + */ +ecma_value_t +ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */ +{ + if (!ecma_is_value_object (value)) + { + return ecma_copy_value (value); + } + + return value; +} /* ecma_copy_value_if_not_object */ + +/** + * Increase reference counter of a value if it is an object. + * + * @return void + */ +void +ecma_ref_if_object (ecma_value_t value) /**< value description */ +{ + if (ecma_is_value_object (value)) + { + ecma_ref_object (ecma_get_object_from_value (value)); + } +} /* ecma_ref_if_object */ + +/** + * Decrease reference counter of a value if it is an object. + * + * @return void + */ +void +ecma_deref_if_object (ecma_value_t value) /**< value description */ +{ + if (ecma_is_value_object (value)) + { + ecma_deref_object (ecma_get_object_from_value (value)); + } +} /* ecma_deref_if_object */ + +/** + * Assign a new value to an ecma-value + * + * Note: + * value previously stored in the property is freed + */ +void +ecma_value_assign_value (ecma_value_t *value_p, /**< [in, out] ecma value */ + ecma_value_t ecma_value) /**< value to assign */ +{ + JERRY_STATIC_ASSERT (ECMA_TYPE_DIRECT == 0, ecma_type_direct_must_be_zero_for_the_next_check); + + if (*value_p == ecma_value) + { + return; + } + + if (ecma_get_value_type_field (ecma_value || *value_p) == ECMA_TYPE_DIRECT) + { + *value_p = ecma_value; + } + else if (ecma_is_value_float_number (ecma_value) && ecma_is_value_float_number (*value_p)) + { + const ecma_number_t *num_src_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (ecma_value); + ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p); + + *num_dst_p = *num_src_p; + } + else + { + ecma_free_value_if_not_object (*value_p); + *value_p = ecma_copy_value_if_not_object (ecma_value); + } +} /* ecma_value_assign_value */ + +/** + * Update the value of a float number to a new value + * + * Note: + * The original value is destroyed. + * + * @return updated ecma value + */ +ecma_value_t +ecma_update_float_number (ecma_value_t float_value, /**< original float value */ + ecma_number_t new_number) /**< updated number value */ +{ + JERRY_ASSERT (ecma_is_value_float_number (float_value)); + + ecma_integer_value_t integer_number = (ecma_integer_value_t) new_number; + ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (float_value); + + if ((ecma_number_t) integer_number == new_number + && ((integer_number == 0) ? ecma_is_number_equal_to_positive_zero (new_number) + : ECMA_IS_INTEGER_NUMBER (integer_number))) + { + ecma_dealloc_number (number_p); + return ecma_make_integer_value (integer_number); + } + + *number_p = new_number; + return float_value; +} /* ecma_update_float_number */ + +/** + * Assign a float number to an ecma-value + * + * Note: + * value previously stored in the property is freed + */ +static void +ecma_value_assign_float_number (ecma_value_t *value_p, /**< [in, out] ecma value */ + ecma_number_t ecma_number) /**< number to assign */ +{ + if (ecma_is_value_float_number (*value_p)) + { + ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p); + + *num_dst_p = ecma_number; + return; + } + + if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT + && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT) + { + ecma_free_value (*value_p); + } + + *value_p = ecma_create_float_number (ecma_number); +} /* ecma_value_assign_float_number */ + +/** + * Assign a number to an ecma-value + * + * Note: + * value previously stored in the property is freed + */ +void +ecma_value_assign_number (ecma_value_t *value_p, /**< [in, out] ecma value */ + ecma_number_t ecma_number) /**< number to assign */ +{ + ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number; + + if ((ecma_number_t) integer_value == ecma_number + && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number) + : ECMA_IS_INTEGER_NUMBER (integer_value))) + { + if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT + && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT) + { + ecma_free_value (*value_p); + } + *value_p = ecma_make_integer_value (integer_value); + return; + } + + ecma_value_assign_float_number (value_p, ecma_number); +} /* ecma_value_assign_number */ + +/** + * Free the ecma value + */ +void +ecma_free_value (ecma_value_t value) /**< value description */ +{ + switch (ecma_get_value_type_field (value)) + { + case ECMA_TYPE_FLOAT: + { + ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); + ecma_dealloc_number (number_p); + break; + } + case ECMA_TYPE_SYMBOL: + case ECMA_TYPE_STRING: + { + ecma_string_t *string_p = (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); + ecma_deref_ecma_string_non_direct (string_p); + break; + } + case ECMA_TYPE_OBJECT: + { + ecma_deref_object (ecma_get_object_from_value (value)); + break; + } +#if JERRY_BUILTIN_BIGINT + case ECMA_TYPE_BIGINT: + { + if (value != ECMA_BIGINT_ZERO) + { + ecma_deref_bigint (ecma_get_extended_primitive_from_value (value)); + } + + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + default: + { + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT + || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING); + + /* no memory is allocated */ + break; + } + } +} /* ecma_free_value */ + +/** + * Free the ecma value + * + * Note: + * this function is similar to ecma_free_value, but it is + * faster for direct values since no function call is performed. + * It also increases the binary size so it is recommended for + * critical code paths only. + * + * @return void + */ +void +ecma_fast_free_value (ecma_value_t value) /**< value description */ +{ + if (ecma_get_value_type_field (value) != ECMA_TYPE_DIRECT) + { + ecma_free_value (value); + } +} /* ecma_fast_free_value */ + +/** + * Free the ecma value if not an object + */ +void +ecma_free_value_if_not_object (ecma_value_t value) /**< value description */ +{ + if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT) + { + ecma_free_value (value); + } +} /* ecma_free_value_if_not_object */ + +/** + * Free an ecma-value object + * + * @return void + */ +void +ecma_free_object (ecma_value_t value) /**< value description */ +{ + ecma_deref_object (ecma_get_object_from_value (value)); +} /* ecma_free_object */ + +/** + * Free an ecma-value number + * + * @return void + */ +void +ecma_free_number (ecma_value_t value) /**< value description */ +{ + JERRY_ASSERT (ecma_is_value_number (value)); + + if (ecma_is_value_float_number (value)) + { + ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); + ecma_dealloc_number (number_p); + } +} /* ecma_free_number */ + +/** + * Get the literal id associated with the given ecma_value type. + * This operation is equivalent to the JavaScript 'typeof' operator. + * + * @returns one of the following value: + * - LIT_MAGIC_STRING_UNDEFINED + * - LIT_MAGIC_STRING_OBJECT + * - LIT_MAGIC_STRING_BOOLEAN + * - LIT_MAGIC_STRING_NUMBER + * - LIT_MAGIC_STRING_STRING + * - LIT_MAGIC_STRING_FUNCTION + */ +lit_magic_string_id_t +ecma_get_typeof_lit_id (ecma_value_t value) /**< input ecma value */ +{ + lit_magic_string_id_t ret_value = LIT_MAGIC_STRING__EMPTY; + + if (ecma_is_value_undefined (value)) + { + ret_value = LIT_MAGIC_STRING_UNDEFINED; + } + else if (ecma_is_value_null (value)) + { + ret_value = LIT_MAGIC_STRING_OBJECT; + } + else if (ecma_is_value_boolean (value)) + { + ret_value = LIT_MAGIC_STRING_BOOLEAN; + } + else if (ecma_is_value_number (value)) + { + ret_value = LIT_MAGIC_STRING_NUMBER; + } + else if (ecma_is_value_string (value)) + { + ret_value = LIT_MAGIC_STRING_STRING; + } + else if (ecma_is_value_symbol (value)) + { + ret_value = LIT_MAGIC_STRING_SYMBOL; + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (value)) + { + ret_value = LIT_MAGIC_STRING_BIGINT; + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + JERRY_ASSERT (ecma_is_value_object (value)); + + ret_value = ecma_op_is_callable (value) ? LIT_MAGIC_STRING_FUNCTION : LIT_MAGIC_STRING_OBJECT; + } + + JERRY_ASSERT (ret_value != LIT_MAGIC_STRING__EMPTY); + + return ret_value; +} /* ecma_get_typeof_lit_id */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.cpp new file mode 100644 index 00000000..1c994091 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.cpp @@ -0,0 +1,1762 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-lcache.h" +#include "ecma-line-info.h" +#include "ecma-property-hashmap.h" + +#include "byte-code.h" +#include "jcontext.h" +#include "jrt-bit-fields.h" +#include "re-compiler.h" + + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +JERRY_STATIC_ASSERT (((int)ECMA_OBJECT_TYPE_MASK >= ((int)ECMA_OBJECT_TYPE__MAX) - 1), + ecma_object_types_must_be_lower_than_the_container_mask); + +JERRY_STATIC_ASSERT (((int)ECMA_OBJECT_TYPE_MASK >= (int)ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX), + ecma_lexical_environment_types_must_be_lower_than_the_container_mask); + +JERRY_STATIC_ASSERT (((int)ECMA_OBJECT_FLAG_EXTENSIBLE == ((int)ECMA_OBJECT_TYPE_MASK) + 1), + ecma_extensible_flag_must_follow_the_object_type); + +JERRY_STATIC_ASSERT ((ECMA_OBJECT_REF_ONE == (ECMA_OBJECT_FLAG_EXTENSIBLE << 1)), + ecma_object_ref_one_must_follow_the_extensible_flag); + +JERRY_STATIC_ASSERT (((ECMA_OBJECT_MAX_REF + ECMA_OBJECT_REF_ONE) == ECMA_OBJECT_REF_MASK), + ecma_object_max_ref_does_not_fill_the_remaining_bits); + +JERRY_STATIC_ASSERT (((ECMA_OBJECT_REF_MASK & (ECMA_OBJECT_TYPE_MASK | ECMA_OBJECT_FLAG_EXTENSIBLE)) == 0), + ecma_object_ref_mask_overlaps_with_object_type_or_extensible); + +JERRY_STATIC_ASSERT ((ECMA_PROPERTY_FLAGS_MASK == ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE), + ecma_property_flags_mask_must_use_the_configurable_enumerable_writable_flags); + +/* These checks are needed by ecma_get_object_base_type. */ +JERRY_STATIC_ASSERT (((int) ECMA_OBJECT_TYPE_BUILT_IN_GENERAL == ((int) ECMA_OBJECT_TYPE_GENERAL | 0x1)) + && (((int) ECMA_OBJECT_TYPE_GENERAL & 0x1) == 0), + ecma_object_type_built_in_general_has_unexpected_value); +JERRY_STATIC_ASSERT (((int) ECMA_OBJECT_TYPE_BUILT_IN_CLASS == ((int) ECMA_OBJECT_TYPE_CLASS | 0x1)) + && (((int) ECMA_OBJECT_TYPE_CLASS & 0x1) == 0), + ecma_object_type_built_in_class_has_unexpected_value); +JERRY_STATIC_ASSERT (((int) ECMA_OBJECT_TYPE_BUILT_IN_ARRAY == ((int) ECMA_OBJECT_TYPE_ARRAY | 0x1)) + && (((int) ECMA_OBJECT_TYPE_ARRAY & 0x1) == 0), + ecma_object_type_built_in_array_has_unexpected_value); + +/** + * Create an object with specified prototype object + * (or NULL prototype if there is not prototype for the object) + * and value of 'Extensible' attribute. + * + * Reference counter's value will be set to one. + * + * @return pointer to the object's descriptor + */ +ecma_object_t * +ecma_create_object (ecma_object_t *prototype_object_p, /**< pointer to prototybe of the object (or NULL) */ + size_t ext_object_size, /**< size of extended objects */ + ecma_object_type_t type) /**< object type */ +{ + ecma_object_t *new_object_p; + + if (ext_object_size > 0) + { + new_object_p = (ecma_object_t *) ecma_alloc_extended_object (ext_object_size); + } + else + { + new_object_p = ecma_alloc_object (); + } + + new_object_p->type_flags_refs = (ecma_object_descriptor_t) (type | ECMA_OBJECT_FLAG_EXTENSIBLE); + + ecma_init_gc_info (new_object_p); + + new_object_p->u1.property_list_cp = JMEM_CP_NULL; + + ECMA_SET_POINTER (new_object_p->u2.prototype_cp, prototype_object_p); + + return new_object_p; +} /* ecma_create_object */ + +/** + * Create a declarative lexical environment with specified outer lexical environment + * (or NULL if the environment is not nested). + * + * See also: ECMA-262 v5, 10.2.1.1 + * + * Reference counter's value will be set to one. + * + * @return pointer to the descriptor of lexical environment + */ +ecma_object_t * +ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer lexical environment */ +{ + ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); + + new_lexical_environment_p->type_flags_refs = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE; + + ecma_init_gc_info (new_lexical_environment_p); + + new_lexical_environment_p->u1.property_list_cp = JMEM_CP_NULL; + + ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p); + + return new_lexical_environment_p; +} /* ecma_create_decl_lex_env */ + +/** + * Create a object lexical environment with specified outer lexical environment + * (or NULL if the environment is not nested), and binding object. + * + * See also: ECMA-262 v5, 10.2.1.2 + * + * Reference counter's value will be set to one. + * + * @return pointer to the descriptor of lexical environment + */ +ecma_object_t * +ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */ + ecma_object_t *binding_obj_p) /**< binding object */ +{ + JERRY_ASSERT (binding_obj_p != NULL && !ecma_is_lexical_environment (binding_obj_p)); + + ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); + + new_lexical_environment_p->type_flags_refs = ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND; + + ecma_init_gc_info (new_lexical_environment_p); + + ECMA_SET_NON_NULL_POINTER (new_lexical_environment_p->u1.bound_object_cp, binding_obj_p); + + ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p); + + return new_lexical_environment_p; +} /* ecma_create_object_lex_env */ + +/** + * Create a lexical environment with a specified size. + * + * @return pointer to the descriptor of the lexical environment + */ +ecma_object_t * +ecma_create_lex_env_class (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */ + size_t lexical_env_size) /**< size of the lexical environment */ +{ + ecma_object_t *new_lexical_environment_p; + + ecma_object_descriptor_t type_flags_refs = ECMA_LEXICAL_ENVIRONMENT_CLASS; + + if (lexical_env_size > 0) + { + new_lexical_environment_p = (ecma_object_t *) ecma_alloc_extended_object (lexical_env_size); + type_flags_refs |= ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA; + } + else + { + new_lexical_environment_p = ecma_alloc_object (); + } + + new_lexical_environment_p->type_flags_refs = type_flags_refs; + + ecma_init_gc_info (new_lexical_environment_p); + + new_lexical_environment_p->u1.property_list_cp = JMEM_CP_NULL; + + ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p); + + return new_lexical_environment_p; +} /* ecma_create_lex_env_class */ + +/** + * Check if the object is lexical environment. + * + * @return true - if object is a lexical environment + * false - otherwise + */ +bool JERRY_ATTR_PURE +ecma_is_lexical_environment (const ecma_object_t *object_p) /**< object or lexical environment */ +{ + JERRY_ASSERT (object_p != NULL); + + return (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK) >= ECMA_LEXICAL_ENVIRONMENT_TYPE_START; +} /* ecma_is_lexical_environment */ + +/** + * Set value of [[Extensible]] object's internal property. + */ +void +ecma_op_ordinary_object_set_extensible (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); + + object_p->type_flags_refs |= ECMA_OBJECT_FLAG_EXTENSIBLE; +} /* ecma_op_ordinary_object_set_extensible */ + +/** + * Get the internal type of an object. + * + * @return type of the object (ecma_object_type_t) + */ +ecma_object_type_t JERRY_ATTR_PURE +ecma_get_object_type (const ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); + + return (ecma_object_type_t) (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK); +} /* ecma_get_object_type */ + +/** + * Get the internal base type of an object. + * + * @return base type of the object (ecma_object_base_type_t) + */ +ecma_object_base_type_t JERRY_ATTR_PURE +ecma_get_object_base_type (const ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (!ecma_is_lexical_environment (object_p)); + + return (ecma_object_base_type_t) (object_p->type_flags_refs & (ECMA_OBJECT_TYPE_MASK - 0x1)); +} /* ecma_get_object_base_type */ + +/** + * Get value of an object if the class matches + * + * @return value of the object if the class matches + * ECMA_VALUE_NOT_FOUND otherwise + */ +bool +ecma_object_class_is (ecma_object_t *object_p, /**< object */ + ecma_object_class_type_t class_id) /**< class id */ +{ + if (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_CLASS) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ext_object_p->u.cls.type == (uint8_t) class_id) + { + return true; + } + } + + return false; +} /* ecma_object_class_is */ + +/** + * Get type of lexical environment. + * + * @return type of the lexical environment (ecma_lexical_environment_type_t) + */ +ecma_lexical_environment_type_t JERRY_ATTR_PURE +ecma_get_lex_env_type (const ecma_object_t *object_p) /**< lexical environment */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p)); + + return (ecma_lexical_environment_type_t) (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK); +} /* ecma_get_lex_env_type */ + +/** + * Get lexical environment's bound object. + * + * @return pointer to ecma object + */ +ecma_object_t *JERRY_ATTR_PURE +ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-bound lexical environment */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND + || (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && !ECMA_LEX_ENV_CLASS_IS_MODULE (object_p))); + + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u1.bound_object_cp); +} /* ecma_get_lex_env_binding_object */ + +/** + * Create a new lexical environment with the same property list as the passed lexical environment + * + * @return pointer to the newly created lexical environment + */ +ecma_object_t * +ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, /**< declarative lexical environment */ + bool copy_values) /**< copy property values as well */ +{ + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + + ecma_object_t *outer_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_object_t *new_lex_env_p = ecma_create_decl_lex_env (outer_lex_env_p); + + jmem_cpointer_t prop_iter_cp = lex_env_p->u1.property_list_cp; + ecma_property_header_t *prop_iter_p; + + JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL); + +#if JERRY_PROPERTY_HASHMAP + prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + + JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL); +#endif /* JERRY_PROPERTY_HASHMAP */ + + do + { + prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (prop_iter_p->types[i])); + + uint8_t prop_attributes = (uint8_t) (prop_iter_p->types[i] & ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_string_t *name_p = ecma_string_from_property_name (prop_iter_p->types[i], prop_pair_p->names_cp[i]); + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (new_lex_env_p, name_p, prop_attributes, NULL); + + ecma_deref_ecma_string (name_p); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + + if (copy_values) + { + property_value_p->value = ecma_copy_value_if_not_object (prop_pair_p->values[i].value); + } + else + { + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + } + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } while (prop_iter_cp != JMEM_CP_NULL); + + ecma_deref_object (lex_env_p); + return new_lex_env_p; +} /* ecma_clone_decl_lexical_environment */ + +/** + * Create a property in an object and link it into + * the object's properties' linked-list (at start of the list). + * + * @return pointer to the newly created property value + */ +static ecma_property_value_t * +ecma_create_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *name_p, /**< property name */ + uint8_t type_and_flags, /**< type and flags, see ecma_property_info_t */ + ecma_property_value_t value, /**< property value */ + ecma_property_t **out_prop_p) /**< [out] the property is also returned + * if this field is non-NULL */ +{ + JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); + JERRY_ASSERT (name_p != NULL); + JERRY_ASSERT (object_p != NULL); + + jmem_cpointer_t *property_list_head_p = &object_p->u1.property_list_cp; + + if (*property_list_head_p != ECMA_NULL_POINTER) + { + /* If the first entry is free (deleted), it is reused. */ + ecma_property_header_t *first_property_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); + +#if JERRY_PROPERTY_HASHMAP + bool has_hashmap = false; + + if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + property_list_head_p = &first_property_p->next_property_cp; + first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); + has_hashmap = true; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); + + if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_DELETED) + { + ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p; + + ecma_property_t name_type; + first_property_pair_p->names_cp[0] = ecma_string_to_property_name (name_p, &name_type); + first_property_p->types[0] = (ecma_property_t) (type_and_flags | name_type); + + ecma_property_t *property_p = first_property_p->types + 0; + + JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); + + if (out_prop_p != NULL) + { + *out_prop_p = property_p; + } + + first_property_pair_p->values[0] = value; + +#if JERRY_PROPERTY_HASHMAP + /* The property must be fully initialized before ecma_property_hashmap_insert + * is called, because the insert operation may reallocate the hashmap, and + * that triggers garbage collection which scans all properties of all objects. + * A not fully initialized but queued property may cause a crash. */ + + if (has_hashmap) + { + ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 0); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + return first_property_pair_p->values + 0; + } + } + + /* Otherwise we create a new property pair and use its second value. */ + ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair (); + + /* Need to query property_list_head_p again and recheck the existennce + * of property hasmap, because ecma_alloc_property_pair may delete them. */ + property_list_head_p = &object_p->u1.property_list_cp; +#if JERRY_PROPERTY_HASHMAP + bool has_hashmap = false; + + if (*property_list_head_p != ECMA_NULL_POINTER) + { + ecma_property_header_t *first_property_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); + + if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + property_list_head_p = &first_property_p->next_property_cp; + has_hashmap = true; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + /* Just copy the previous value (no need to decompress, compress). */ + first_property_pair_p->header.next_property_cp = *property_list_head_p; + first_property_pair_p->header.types[0] = ECMA_PROPERTY_TYPE_DELETED; + first_property_pair_p->names_cp[0] = LIT_INTERNAL_MAGIC_STRING_DELETED; + + ecma_property_t name_type; + first_property_pair_p->names_cp[1] = ecma_string_to_property_name (name_p, &name_type); + + first_property_pair_p->header.types[1] = (ecma_property_t) (type_and_flags | name_type); + + ECMA_SET_NON_NULL_POINTER (*property_list_head_p, &first_property_pair_p->header); + + ecma_property_t *property_p = first_property_pair_p->header.types + 1; + + JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); + + if (out_prop_p != NULL) + { + *out_prop_p = property_p; + } + + first_property_pair_p->values[1] = value; + +#if JERRY_PROPERTY_HASHMAP + /* See the comment before the other ecma_property_hashmap_insert above. */ + + if (has_hashmap) + { + ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 1); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + return first_property_pair_p->values + 1; +} /* ecma_create_property */ + +/** + * Create named data property with given name, attributes and undefined value + * in the specified object. + * + * @return pointer to the newly created property value + */ +ecma_property_value_t * +ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< property name */ + uint8_t prop_attributes, /**< property attributes (See: ecma_property_flags_t) */ + ecma_property_t **out_prop_p) /**< [out] the property is also returned + * if this field is non-NULL */ +{ + JERRY_ASSERT (object_p != NULL && name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p) || !ecma_op_object_is_fast_array (object_p)); + JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); + JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE) == 0); + + uint8_t type_and_flags = ECMA_PROPERTY_FLAG_DATA | prop_attributes; + + ecma_property_value_t value; + value.value = ECMA_VALUE_UNDEFINED; + + return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p); +} /* ecma_create_named_data_property */ + +/** + * Create named accessor property with given name, attributes, getter and setter. + * + * @return pointer to the newly created property value + */ +ecma_property_value_t * +ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< property name */ + ecma_object_t *get_p, /**< getter */ + ecma_object_t *set_p, /**< setter */ + uint8_t prop_attributes, /**< property attributes */ + ecma_property_t **out_prop_p) /**< [out] the property is also returned + * if this field is non-NULL */ +{ + JERRY_ASSERT (object_p != NULL && name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (object_p) || !ecma_op_object_is_fast_array (object_p)); + JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); + JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE) == 0); + + uint8_t type_and_flags = prop_attributes; + + ecma_property_value_t value; +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, get_p); + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, set_p); + ECMA_SET_NON_NULL_POINTER (value.getter_setter_pair_cp, getter_setter_pair_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (value.getter_setter_pair.getter_cp, get_p); + ECMA_SET_POINTER (value.getter_setter_pair.setter_cp, set_p); +#endif /* JERRY_CPOINTER_32_BIT */ + + return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p); +} /* ecma_create_named_accessor_property */ + +#if JERRY_MODULE_SYSTEM +/** + * Create property reference + */ +void +ecma_create_named_reference_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< property name */ + ecma_value_t reference) /**< property reference */ +{ + JERRY_ASSERT (object_p != NULL && name_p != NULL); + JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); + JERRY_ASSERT ((ecma_is_lexical_environment (object_p) + && ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && ECMA_LEX_ENV_CLASS_IS_MODULE (object_p)) + || ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE)); + + uint8_t type_and_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE; + ecma_property_value_t value; + + value.value = reference; + + ecma_create_property (object_p, name_p, type_and_flags, value, NULL); +} /* ecma_create_named_reference_property */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Find named data property or named accessor property in a specified object. + * + * @return pointer to the property, if it is found, + * NULL - otherwise. + */ +ecma_property_t * +ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in */ + ecma_string_t *name_p) /**< property's name */ +{ + JERRY_ASSERT (obj_p != NULL); + JERRY_ASSERT (name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (obj_p) || !ecma_op_object_is_fast_array (obj_p)); + +#if JERRY_LCACHE + ecma_property_t *property_p = ecma_lcache_lookup (obj_p, name_p); + if (property_p != NULL) + { + return property_p; + } +#else /* !JERRY_LCACHE */ + ecma_property_t *property_p = NULL; +#endif /* JERRY_LCACHE */ + + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + jmem_cpointer_t property_real_name_cp; + property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p, name_p, &property_real_name_cp); +#if JERRY_LCACHE + if (property_p != NULL && !ecma_is_property_lcached (property_p)) + { + ecma_lcache_insert (obj_p, property_real_name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + return property_p; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if JERRY_PROPERTY_HASHMAP + uint32_t steps = 0; +#endif /* JERRY_PROPERTY_HASHMAP */ + jmem_cpointer_t property_name_cp = ECMA_NULL_POINTER; + + if (ECMA_IS_DIRECT_STRING (name_p)) + { + ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p); + property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p); + + JERRY_ASSERT (prop_name_type > 0); + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (prop_pair_p->names_cp[0] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == prop_name_type) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[0])); + + property_p = prop_iter_p->types + 0; + break; + } + + if (prop_pair_p->names_cp[1] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == prop_name_type) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[1])); + + property_p = prop_iter_p->types + 1; + break; + } + +#if JERRY_PROPERTY_HASHMAP + steps++; +#endif /* JERRY_PROPERTY_HASHMAP */ + prop_iter_cp = prop_iter_p->next_property_cp; + } + } + else + { + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == ECMA_DIRECT_STRING_PTR) + { + property_name_cp = prop_pair_p->names_cp[0]; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp); + + if (ecma_compare_ecma_non_direct_strings (name_p, prop_name_p)) + { + property_p = prop_iter_p->types + 0; + break; + } + } + + if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == ECMA_DIRECT_STRING_PTR) + { + property_name_cp = prop_pair_p->names_cp[1]; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp); + + if (ecma_compare_ecma_non_direct_strings (name_p, prop_name_p)) + { + property_p = prop_iter_p->types + 1; + break; + } + } + +#if JERRY_PROPERTY_HASHMAP + steps++; +#endif /* JERRY_PROPERTY_HASHMAP */ + prop_iter_cp = prop_iter_p->next_property_cp; + } + } + +#if JERRY_PROPERTY_HASHMAP + if (steps >= (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 2)) + { + ecma_property_hashmap_create (obj_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if JERRY_LCACHE + if (property_p != NULL && !ecma_is_property_lcached (property_p)) + { + ecma_lcache_insert (obj_p, property_name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + + return property_p; +} /* ecma_find_named_property */ + +/** + * Get named data property or named access property in specified object. + * + * Warning: + * the property must exist + * + * @return pointer to the property, if it is found, + * NULL - otherwise. + */ +ecma_property_value_t * +ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property in */ + ecma_string_t *name_p) /**< property's name */ +{ + JERRY_ASSERT (obj_p != NULL); + JERRY_ASSERT (name_p != NULL); + JERRY_ASSERT (ecma_is_lexical_environment (obj_p) || !ecma_op_object_is_fast_array (obj_p)); + + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); + + JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p)); + + return ECMA_PROPERTY_VALUE_PTR (property_p); +} /* ecma_get_named_data_property */ + +/** + * Delete the object's property referenced by its value pointer. + * + * Note: specified property must be owned by specified object. + */ +void +ecma_delete_property (ecma_object_t *object_p, /**< object */ + ecma_property_value_t *prop_value_p) /**< property value reference */ +{ + jmem_cpointer_t cur_prop_cp = object_p->u1.property_list_cp; + + ecma_property_header_t *prev_prop_p = NULL; + +#if JERRY_PROPERTY_HASHMAP + ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP; + + if (cur_prop_cp != JMEM_CP_NULL) + { + ecma_property_header_t *cur_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, cur_prop_cp); + + if (cur_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prev_prop_p = cur_prop_p; + cur_prop_cp = cur_prop_p->next_property_cp; + hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (cur_prop_cp != JMEM_CP_NULL) + { + ecma_property_header_t *cur_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, cur_prop_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (cur_prop_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p; + + for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if ((prop_pair_p->values + i) == prop_value_p) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (cur_prop_p->types[i])); + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP) + { + hashmap_status = ecma_property_hashmap_delete (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + ecma_gc_free_property (object_p, prop_pair_p, i); + cur_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED; + prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED; + + JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); + + if (cur_prop_p->types[1 - i] != ECMA_PROPERTY_TYPE_DELETED) + { +#if JERRY_PROPERTY_HASHMAP + /* The other property is still valid. */ + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + return; + } + + JERRY_ASSERT (cur_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED); + + if (prev_prop_p == NULL) + { + object_p->u1.property_list_cp = cur_prop_p->next_property_cp; + } + else + { + prev_prop_p->next_property_cp = cur_prop_p->next_property_cp; + } + + ecma_dealloc_property_pair ((ecma_property_pair_t *) cur_prop_p); + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + return; + } + } + + prev_prop_p = cur_prop_p; + cur_prop_cp = cur_prop_p->next_property_cp; + } +} /* ecma_delete_property */ + +/** + * Check whether the object contains a property + */ +static void +ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ecma-object */ + const ecma_property_value_t *prop_value_p, /**< property value */ + bool is_data) /**< property should be data property */ +{ +#ifndef JERRY_NDEBUG + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL); + + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + + while (prop_iter_cp != JMEM_CP_NULL) + { + prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if ((prop_pair_p->values + i) == prop_value_p) + { + JERRY_ASSERT (is_data == ((prop_pair_p->header.types[i] & ECMA_PROPERTY_FLAG_DATA) != 0)); + return; + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +#else /* JERRY_NDEBUG */ + JERRY_UNUSED (object_p); + JERRY_UNUSED (prop_value_p); + JERRY_UNUSED (is_data); +#endif /* !JERRY_NDEBUG */ +} /* ecma_assert_object_contains_the_property */ + +/** + * Assign value to named data property + * + * Note: + * value previously stored in the property is freed + * + * @return void + */ +void +ecma_named_data_property_assign_value (ecma_object_t *obj_p, /**< object */ + ecma_property_value_t *prop_value_p, /**< property value reference */ + ecma_value_t value) /**< value to assign */ +{ + ecma_assert_object_contains_the_property (obj_p, prop_value_p, true); + + ecma_value_assign_value (&prop_value_p->value, value); +} /* ecma_named_data_property_assign_value */ + +/** + * Get named accessor property getter-setter-pair + * + * @return pointer to object's getter-setter pair + */ +ecma_getter_setter_pointers_t * +ecma_get_named_accessor_property (const ecma_property_value_t *prop_value_p) /**< property value reference */ +{ +#if JERRY_CPOINTER_32_BIT + return ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); +#else /* !JERRY_CPOINTER_32_BIT */ + return (ecma_getter_setter_pointers_t *) &prop_value_p->getter_setter_pair; +#endif /* JERRY_CPOINTER_32_BIT */ +} /* ecma_get_named_accessor_property */ + +/** + * Set getter of named accessor property + */ +void +ecma_set_named_accessor_property_getter (ecma_object_t *object_p, /**< the property's container */ + ecma_property_value_t *prop_value_p, /**< property value reference */ + ecma_object_t *getter_p) /**< getter object */ +{ + ecma_assert_object_contains_the_property (object_p, prop_value_p, false); + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, getter_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.getter_cp, getter_p); +#endif /* JERRY_CPOINTER_32_BIT */ +} /* ecma_set_named_accessor_property_getter */ + +/** + * Set setter of named accessor property + */ +void +ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the property's container */ + ecma_property_value_t *prop_value_p, /**< property value reference */ + ecma_object_t *setter_p) /**< setter object */ +{ + ecma_assert_object_contains_the_property (object_p, prop_value_p, false); + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, setter_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_cp, setter_p); +#endif /* JERRY_CPOINTER_32_BIT */ +} /* ecma_set_named_accessor_property_setter */ + +#if JERRY_MODULE_SYSTEM + +/** + * Construct a reference to a given property + * + * @return property reference + */ +ecma_value_t +ecma_property_to_reference (ecma_property_t *property_p) /**< data or reference property */ +{ + ecma_property_value_t *referenced_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + return referenced_value_p->value; + } + + jmem_cpointer_tag_t offset = (jmem_cpointer_tag_t) (((uintptr_t) property_p) & 0x1); + +#if JERRY_CPOINTER_32_BIT + if (offset != 0) + { + --referenced_value_p; + } +#else /* !JERRY_CPOINTER_32_BIT */ + if (offset == 0) + { + ++referenced_value_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ + + JERRY_ASSERT ((((uintptr_t) referenced_value_p) & (((uintptr_t) 1 << JMEM_ALIGNMENT_LOG) - 1)) == 0); + + ecma_value_t result; + ECMA_SET_NON_NULL_POINTER_TAG (result, referenced_value_p, offset); + return result; +} /* ecma_property_to_reference */ + +/** + * Gets the referenced property value + * + * @return pointer to the value + */ +ecma_property_value_t * +ecma_get_property_value_from_named_reference (ecma_property_value_t *reference_p) /**< data property reference */ +{ + ecma_value_t value = reference_p->value; + reference_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_property_value_t, value); + +#if JERRY_CPOINTER_32_BIT + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (value)) + { + ++reference_p; + } +#else /* !JERRY_CPOINTER_32_BIT */ + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (value)) + { + --reference_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ + + return reference_p; +} /* ecma_get_property_value_from_named_reference */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Get property's 'Writable' attribute value + * + * @return true - property is writable, + * false - otherwise + */ +bool +ecma_is_property_writable (ecma_property_t property) /**< property */ +{ + JERRY_ASSERT (property & ECMA_PROPERTY_FLAG_DATA); + + return (property & ECMA_PROPERTY_FLAG_WRITABLE) != 0; +} /* ecma_is_property_writable */ + +/** + * Set property's 'Writable' attribute value + */ +void +ecma_set_property_writable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_writable) /**< new value for writable flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (*property_p)); + + if (is_writable) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_WRITABLE); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_WRITABLE); + } +} /* ecma_set_property_writable_attr */ + +/** + * Get property's 'Enumerable' attribute value + * + * @return true - property is enumerable, + * false - otherwise + */ +bool +ecma_is_property_enumerable (ecma_property_t property) /**< property */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (property)); + + return (property & ECMA_PROPERTY_FLAG_ENUMERABLE) != 0; +} /* ecma_is_property_enumerable */ + +/** + * Set property's 'Enumerable' attribute value + */ +void +ecma_set_property_enumerable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_enumerable) /**< new value for enumerable flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (is_enumerable) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_ENUMERABLE); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_ENUMERABLE); + } +} /* ecma_set_property_enumerable_attr */ + +/** + * Get property's 'Configurable' attribute value + * + * @return true - property is configurable, + * false - otherwise + */ +bool +ecma_is_property_configurable (ecma_property_t property) /**< property */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (property)); + + return (property & ECMA_PROPERTY_FLAG_CONFIGURABLE) != 0; +} /* ecma_is_property_configurable */ + +/** + * Set property's 'Configurable' attribute value + */ +void +ecma_set_property_configurable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_configurable) /**< new value for configurable flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (is_configurable) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_CONFIGURABLE); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_CONFIGURABLE); + } +} /* ecma_set_property_configurable_attr */ + +#if JERRY_LCACHE + +/** + * Check whether the property is registered in LCache + * + * @return true / false + */ +bool +ecma_is_property_lcached (ecma_property_t *property_p) /**< property */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + return (*property_p & ECMA_PROPERTY_FLAG_LCACHED) != 0; +} /* ecma_is_property_lcached */ + +/** + * Set value of flag indicating whether the property is registered in LCache + */ +void +ecma_set_property_lcached (ecma_property_t *property_p, /**< property */ + bool is_lcached) /**< new value for lcached flag */ +{ + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + if (is_lcached) + { + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_LCACHED); + } + else + { + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_LCACHED); + } +} /* ecma_set_property_lcached */ + +#endif /* JERRY_LCACHE */ + +/** + * Construct empty property descriptor, i.e.: + * property descriptor with all is_defined flags set to false and the rest - to default value. + * + * @return empty property descriptor + */ +ecma_property_descriptor_t +ecma_make_empty_property_descriptor (void) +{ + ecma_property_descriptor_t prop_desc; + + prop_desc.flags = 0; + prop_desc.value = ECMA_VALUE_UNDEFINED; + prop_desc.get_p = NULL; + prop_desc.set_p = NULL; + + return prop_desc; +} /* ecma_make_empty_property_descriptor */ + +/** + * Free values contained in the property descriptor + * and make it empty property descriptor + */ +void +ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_free_value (prop_desc_p->value); + } + + if ((prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && prop_desc_p->get_p != NULL) + { + ecma_deref_object (prop_desc_p->get_p); + } + + if ((prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) && prop_desc_p->set_p != NULL) + { + ecma_deref_object (prop_desc_p->set_p); + } + + *prop_desc_p = ecma_make_empty_property_descriptor (); +} /* ecma_free_property_descriptor */ + +/** + * Increase ref count of an extended primitve value. + */ +void +ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p) /**< extended primitve value */ +{ + if (JERRY_LIKELY (primitve_p->refs_and_type < ECMA_EXTENDED_PRIMITIVE_MAX_REF)) + { + primitve_p->refs_and_type += ECMA_EXTENDED_PRIMITIVE_REF_ONE; + } + else + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } +} /* ecma_ref_extended_primitive */ + +/** + * Decrease ref count of an error reference. + */ +void +ecma_deref_exception (ecma_extended_primitive_t *error_ref_p) /**< error reference */ +{ + JERRY_ASSERT (error_ref_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE); + + error_ref_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE; + + if (error_ref_p->refs_and_type < ECMA_EXTENDED_PRIMITIVE_REF_ONE) + { + ecma_free_value (error_ref_p->u.value); + jmem_pools_free (error_ref_p, sizeof (ecma_extended_primitive_t)); + } +} /* ecma_deref_exception */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Decrease ref count of a bigint value. + */ +void +ecma_deref_bigint (ecma_extended_primitive_t *bigint_p) /**< bigint value */ +{ + JERRY_ASSERT (bigint_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE); + + bigint_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE; + + if (bigint_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE) + { + return; + } + + uint32_t size = ECMA_BIGINT_GET_SIZE (bigint_p); + + JERRY_ASSERT (size > 0); + + size_t mem_size = ECMA_BIGINT_GET_BYTE_SIZE (size) + sizeof (ecma_extended_primitive_t); + jmem_heap_free_block (bigint_p, mem_size); +} /* ecma_deref_bigint */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Create an error reference from a given value. + * + * Note: + * Reference of the value is taken. + * + * @return error reference value + */ +ecma_value_t +ecma_create_exception (ecma_value_t value, /**< referenced value */ + uint32_t options) /**< ECMA_ERROR_API_* options */ +{ + ecma_extended_primitive_t *error_ref_p; + error_ref_p = (ecma_extended_primitive_t *) jmem_pools_alloc (sizeof (ecma_extended_primitive_t)); + + error_ref_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | options; + error_ref_p->u.value = value; + return ecma_make_extended_primitive_value (error_ref_p, ECMA_TYPE_ERROR); +} /* ecma_create_exception */ + +/** + * Create an error reference from the currently thrown error value. + * + * @return error reference value + */ +ecma_value_t +ecma_create_exception_from_context (void) +{ + uint32_t options = 0; + uint32_t status_flags = JERRY_CONTEXT (status_flags); + + if (status_flags & ECMA_STATUS_ABORT) + { + options |= ECMA_ERROR_API_FLAG_ABORT; + } + +#if JERRY_VM_THROW + if (status_flags & ECMA_STATUS_ERROR_THROWN) + { + options |= ECMA_ERROR_API_FLAG_THROW_CAPTURED; + } +#endif /* JERRY_VM_THROW */ + + return ecma_create_exception (jcontext_take_exception (), options); +} /* ecma_create_exception_from_context */ + +/** + * Create an exception from a given object. + * + * Note: + * Reference of the object is taken. + * + * @return exception value + */ +ecma_value_t +ecma_create_exception_from_object (ecma_object_t *object_p) /**< referenced object */ +{ + return ecma_create_exception (ecma_make_object_value (object_p), 0); +} /* ecma_create_exception_from_object */ + +/** + * Raise a new exception from the argument exception value. + * + * Note: the argument exceptions reference count is decreased + */ +void +ecma_throw_exception (ecma_value_t value) /**< error reference */ +{ + JERRY_ASSERT (!jcontext_has_pending_exception () && !jcontext_has_pending_abort ()); + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + JERRY_ASSERT (error_ref_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE); + + ecma_value_t referenced_value = error_ref_p->u.value; + uint32_t status_flags = JERRY_CONTEXT (status_flags); + + status_flags |= (ECMA_STATUS_EXCEPTION +#if JERRY_VM_THROW + | ECMA_STATUS_ERROR_THROWN +#endif /* JERRY_VM_THROW */ + | ECMA_STATUS_ABORT); + + if (!(error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_ABORT)) + { + status_flags &= ~(uint32_t) ECMA_STATUS_ABORT; + } + +#if JERRY_VM_THROW + if (!(error_ref_p->refs_and_type & ECMA_ERROR_API_FLAG_THROW_CAPTURED)) + { + status_flags &= ~(uint32_t) ECMA_STATUS_ERROR_THROWN; + } +#endif /* JERRY_VM_THROW */ + + JERRY_CONTEXT (status_flags) = status_flags; + + if (error_ref_p->refs_and_type >= 2 * ECMA_EXTENDED_PRIMITIVE_REF_ONE) + { + error_ref_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE; + referenced_value = ecma_copy_value (referenced_value); + } + else + { + jmem_pools_free (error_ref_p, sizeof (ecma_extended_primitive_t)); + } + + JERRY_CONTEXT (error_value) = referenced_value; +} /* ecma_throw_exception */ + +/** + * Decrease the reference counter of a script value. + */ +void +ecma_script_deref (ecma_value_t script_value) /**< script value */ +{ + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + script_p->refs_and_type -= CBC_SCRIPT_REF_ONE; + + if (script_p->refs_and_type >= CBC_SCRIPT_REF_ONE) + { + return; + } + + size_t script_size = sizeof (cbc_script_t); + uint32_t type = script_p->refs_and_type; + + if (type & CBC_SCRIPT_HAS_USER_VALUE) + { + script_size += sizeof (ecma_value_t); + + if (!(type & CBC_SCRIPT_USER_VALUE_IS_OBJECT)) + { + ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); + + JERRY_ASSERT (!ecma_is_value_object (user_value)); + ecma_free_value (user_value); + } + } + +#if JERRY_SOURCE_NAME + ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_name)); +#endif /* JERRY_SOURCE_NAME */ + +#if JERRY_MODULE_SYSTEM + if (type & CBC_SCRIPT_HAS_IMPORT_META) + { + JERRY_ASSERT (!(type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)); + JERRY_ASSERT (ecma_is_value_object (CBC_SCRIPT_GET_IMPORT_META (script_p, type))); + + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_MODULE_SYSTEM */ + +#if JERRY_FUNCTION_TO_STRING + ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_code)); + + if (type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS) + { + ecma_deref_ecma_string (ecma_get_string_from_value (CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, type))); + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + + jmem_heap_free_block (script_p, script_size); +} /* ecma_script_deref */ + +/** + * Increase reference counter of Compact + * Byte Code or regexp byte code. + */ +void +ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ +{ + /* Abort program if maximum reference number is reached. */ + if (bytecode_p->refs >= UINT16_MAX) + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } + + bytecode_p->refs++; +} /* ecma_bytecode_ref */ + +/** + * Decrease reference counter of Compact + * Byte Code or regexp byte code. + */ +void +ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ +{ + JERRY_ASSERT (bytecode_p->refs > 0); + JERRY_ASSERT (!CBC_IS_FUNCTION (bytecode_p->status_flags) + || !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + + bytecode_p->refs--; + + if (bytecode_p->refs > 0) + { + /* Non-zero reference counter. */ + return; + } + + if (CBC_IS_FUNCTION (bytecode_p->status_flags)) + { + ecma_value_t *literal_start_p = NULL; + uint32_t literal_end; + uint32_t const_literal_end; + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_p; + literal_end = args_p->literal_end; + const_literal_end = args_p->const_literal_end; + + literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint16_arguments_t)); + literal_start_p -= args_p->register_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_p; + literal_end = args_p->literal_end; + const_literal_end = args_p->const_literal_end; + + literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint8_arguments_t)); + literal_start_p -= args_p->register_end; + } + + for (uint32_t i = const_literal_end; i < literal_end; i++) + { + ecma_compiled_code_t *bytecode_literal_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, literal_start_p[i]); + + /* Self references are ignored. */ + if (bytecode_literal_p != bytecode_p) + { + ecma_bytecode_deref (bytecode_literal_p); + } + } + + ecma_script_deref (((cbc_uint8_arguments_t *) bytecode_p)->script_value); + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + ecma_collection_t *collection_p = ecma_compiled_code_get_tagged_template_collection (bytecode_p); + + /* Since the objects in the tagged template collection are not strong referenced anymore by the compiled code + we can treat them as 'new' objects. */ + JERRY_CONTEXT (ecma_gc_new_objects) += collection_p->item_count * 2; + ecma_collection_free_template_literal (collection_p); + } + +#if JERRY_LINE_INFO + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + ecma_line_info_free (ecma_compiled_code_get_line_info (bytecode_p)); + } +#endif /* JERRY_LINE_INFO */ + + } + else + { +#if JERRY_BUILTIN_REGEXP + re_compiled_code_t *re_bytecode_p = (re_compiled_code_t *) bytecode_p; + + ecma_deref_ecma_string (ecma_get_string_from_value (re_bytecode_p->source)); +#endif /* JERRY_BUILTIN_REGEXP */ + } + + jmem_heap_free_block (bytecode_p, ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); +} /* ecma_bytecode_deref */ + +/** + * Gets the script data asigned to a script / module / function + * + * @return script data - if available, JMEM_CP_NULL - otherwise + */ +ecma_value_t +ecma_script_get_from_value (ecma_value_t value) /**< compiled code */ +{ + if (!ecma_is_value_object (value)) + { + return JMEM_CP_NULL; + } + + ecma_object_t *object_p = ecma_get_object_from_value (value); + const ecma_compiled_code_t *bytecode_p = NULL; + + while (true) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_SCRIPT) + { + bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); + break; + } + +#if JERRY_MODULE_SYSTEM + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_MODULE) + { + ecma_module_t *module_p = (ecma_module_t *) object_p; + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)) + { + bytecode_p = module_p->u.compiled_code_p; + break; + } + } +#endif /* JERRY_MODULE_SYSTEM */ + return JMEM_CP_NULL; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + object_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_object_p->u.bound_function.target_function); + continue; + } + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + return ((ecma_extended_object_t *) object_p)->u.constructor_function.script_value; + } + default: + { + return JMEM_CP_NULL; + } + } + + JERRY_ASSERT (bytecode_p != NULL); + return ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + } +} /* ecma_script_get_from_value */ + +/** + * Resolve the position of the arguments list start of the compiled code + * + * @return start position of the arguments list start of the compiled code + */ +ecma_value_t * +ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + + uint8_t *byte_p = (uint8_t *) bytecode_header_p; + byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG; + + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)) + { + return ((ecma_value_t *) byte_p); + } + + if (JERRY_LIKELY (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS))) + { + return ((ecma_value_t *) byte_p) - ((cbc_uint8_arguments_t *) bytecode_header_p)->argument_end; + } + + return ((ecma_value_t *) byte_p) - ((cbc_uint16_arguments_t *) bytecode_header_p)->argument_end; +} /* ecma_compiled_code_resolve_arguments_start */ + +/** + * Resolve the position of the function name of the compiled code + * + * @return position of the function name of the compiled code + */ +ecma_value_t * +ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + return base_p; +} /* ecma_compiled_code_resolve_function_name */ + +/** + * Get the tagged template collection of the compiled code + * + * @return pointer to the tagged template collection + */ +ecma_collection_t * +ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS); + + ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p); + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]); +} /* ecma_compiled_code_get_tagged_template_collection */ + +#if JERRY_LINE_INFO + +/** + * Get the line info data from the byte code + * + * @return pointer to the line info data + */ +uint8_t * +ecma_compiled_code_get_line_info (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO); + + ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + base_p--; + } + + return ECMA_GET_INTERNAL_VALUE_POINTER (uint8_t, base_p[-1]); +} /* ecma_compiled_code_get_line_info */ + +#endif /* JERRY_LINE_INFO */ + +/** + * Get the source name of a compiled code. + * + * @return source name value + */ +ecma_value_t +ecma_get_source_name (const ecma_compiled_code_t *bytecode_p) /**< compiled code */ +{ +#if JERRY_SOURCE_NAME +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + return ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value)->source_name; +#else /* !JERRY_SOURCE_NAME */ + JERRY_UNUSED (bytecode_p); + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); +#endif /* !JERRY_SOURCE_NAME */ +} /* ecma_get_source_name */ + +#if (JERRY_STACK_LIMIT != 0) +/** + * Check the current stack usage by calculating the difference from the initial stack base. + * + * @return current stack usage in bytes + */ +uintptr_t JERRY_ATTR_NOINLINE +ecma_get_current_stack_usage (void) +{ + volatile int __sp; + return (uintptr_t) (JERRY_CONTEXT (stack_base) - (uintptr_t) &__sp); +} /* ecma_get_current_stack_usage */ + +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.h new file mode 100644 index 00000000..0e98ea24 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-helpers.h @@ -0,0 +1,524 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_HELPERS_H +#define ECMA_HELPERS_H + +#include "ecma-globals.h" + +#include "jmem.h" +#include "lit-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmahelpers Helpers for operations with ECMA data types + * @{ + */ + +/** + * Get value of pointer from specified non-null compressed pointer. + */ +#define ECMA_GET_NON_NULL_POINTER(type, field) JMEM_CP_GET_NON_NULL_POINTER (type, field) + +/** + * Extract value of pointer from specified pointer-tag value + */ +#define ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG(type, field) \ + JMEM_CP_GET_NON_NULL_POINTER_FROM_POINTER_TAG (type, field) + +/** + * Get value of pointer from specified compressed pointer. + */ +#define ECMA_GET_POINTER(type, field) JMEM_CP_GET_POINTER (type, field) + +/** + * Set value of non-null compressed pointer so that it will correspond + * to specified non_compressed_pointer. + */ +#define ECMA_SET_NON_NULL_POINTER(field, non_compressed_pointer) \ + JMEM_CP_SET_NON_NULL_POINTER (field, non_compressed_pointer) + +/** + * Set value of pointer-tag value so that it will correspond + * to specified non_compressed_pointer along with tag + */ +#define ECMA_SET_NON_NULL_POINTER_TAG(field, non_compressed_pointer, tag) \ + JMEM_CP_SET_NON_NULL_POINTER_TAG (field, non_compressed_pointer, tag) + +/** + * Set value of compressed pointer so that it will correspond + * to specified non_compressed_pointer. + */ +#define ECMA_SET_POINTER(field, non_compressed_pointer) JMEM_CP_SET_POINTER (field, non_compressed_pointer) + +/** + * Get value of each tag bit from specified pointer-tag value + */ +#define ECMA_GET_FIRST_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (field) /**< get first tag bit from jmem_cpointer_tag_t **/ +#define ECMA_GET_SECOND_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (field) /**< get second tag bit from jmem_cpointer_tag_t **/ +#define ECMA_GET_THIRD_BIT_FROM_POINTER_TAG(field) \ + JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG (field) /**< get third tag bit from jmem_cpointer_tag_t **/ + +/** + * Set value of each tag bit to specified pointer-tag value + */ +#define ECMA_SET_FIRST_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_FIRST_BIT_TO_POINTER_TAG (field) /**< set first tag bit to jmem_cpointer_tag_t **/ +#define ECMA_SET_SECOND_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_SECOND_BIT_TO_POINTER_TAG (field) /**< set second tag bit to jmem_cpointer_tag_t **/ +#define ECMA_SET_THIRD_BIT_TO_POINTER_TAG(field) \ + JMEM_CP_SET_THIRD_BIT_TO_POINTER_TAG (field) /**< set third tag bit to jmem_cpointer_tag_t **/ + +/** + * Status flags for ecma_string_get_chars function + */ +typedef enum +{ + ECMA_STRING_FLAG_EMPTY = 0, /**< No options are provided. */ + ECMA_STRING_FLAG_IS_ASCII = (1 << 0), /**< The string contains only ASCII characters. */ + ECMA_STRING_FLAG_REHASH_NEEDED = (1 << 1), /**< The hash of the string must be recalculated. + * For more details see ecma_append_chars_to_string */ + ECMA_STRING_FLAG_IS_UINT32 = (1 << 2), /**< The string repesents an UINT32 number */ + ECMA_STRING_FLAG_MUST_BE_FREED = (1 << 3), /**< The returned buffer must be freed */ +} ecma_string_flag_t; + +/** + * Underscore is ignored when this option is passed. + */ +#define ECMA_CONVERSION_ALLOW_UNDERSCORE 0x1 + +/** + * Convert ecma-string's contents to a cesu-8 string and put it into a buffer. + */ +#define ECMA_STRING_TO_UTF8_STRING(ecma_str_ptr, /**< ecma string pointer */ \ + utf8_ptr, /**< [out] output buffer pointer */ \ + utf8_str_size) /**< [out] output buffer size */ \ + lit_utf8_size_t utf8_str_size; \ + uint8_t utf8_ptr##flags = ECMA_STRING_FLAG_EMPTY; \ + const lit_utf8_byte_t *utf8_ptr = ecma_string_get_chars (ecma_str_ptr, &utf8_str_size, NULL, NULL, &utf8_ptr##flags); + +/** + * Free the cesu-8 string buffer allocated by 'ECMA_STRING_TO_UTF8_STRING' + */ +#define ECMA_FINALIZE_UTF8_STRING(utf8_ptr, /**< pointer to character buffer */ \ + utf8_str_size) /**< buffer size */ \ + if (utf8_ptr##flags & ECMA_STRING_FLAG_MUST_BE_FREED) \ + { \ + JERRY_ASSERT (utf8_ptr != NULL); \ + jmem_heap_free_block ((void *) utf8_ptr, utf8_str_size); \ + } + +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY + +/** + * Set an internal property value from pointer. + */ +#define ECMA_SET_INTERNAL_VALUE_POINTER(field, pointer) ((field) = ((ecma_value_t) pointer)) + +/** + * Set an internal property value from pointer. Pointer can be NULL. + */ +#define ECMA_SET_INTERNAL_VALUE_ANY_POINTER(field, pointer) ((field) = ((ecma_value_t) pointer)) + +/** + * Convert an internal property value to pointer. + */ +#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) ((type *) field) + +/** + * Convert an internal property value to pointer. Result can be NULL. + */ +#define ECMA_GET_INTERNAL_VALUE_ANY_POINTER(type, field) ((type *) field) + +/** + * Checks whether an internal property is NULL. + */ +#define ECMA_IS_INTERNAL_VALUE_NULL(field) ((field) == ((ecma_value_t) NULL)) + +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +/** + * Set an internal property value from pointer. + */ +#define ECMA_SET_INTERNAL_VALUE_POINTER(field, pointer) ECMA_SET_NON_NULL_POINTER (field, pointer) + +/** + * Set an internal property value from pointer. Pointer can be NULL. + */ +#define ECMA_SET_INTERNAL_VALUE_ANY_POINTER(field, pointer) ECMA_SET_POINTER (field, pointer) + +/** + * Convert an internal property value to pointer. + */ +#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) ECMA_GET_NON_NULL_POINTER (type, field) + +/** + * Convert an internal property value to pointer. Result can be NULL. + */ +#define ECMA_GET_INTERNAL_VALUE_ANY_POINTER(type, field) ECMA_GET_POINTER (type, field) + +/** + * Checks whether an internal property is NULL. + */ +#define ECMA_IS_INTERNAL_VALUE_NULL(field) ((field) == ((ecma_value_t) JMEM_CP_NULL)) + +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ + +/** + * Convert boolean to bitfield value. + */ +#define ECMA_BOOL_TO_BITFIELD(x) ((x) ? 1 : 0) + +/** + * Check whether the given type is ECMA_OBJECT_TYPE_PROXY + * + * @param type object type + */ +#define ECMA_OBJECT_TYPE_IS_PROXY(type) (JERRY_UNLIKELY ((type) == ECMA_OBJECT_TYPE_PROXY)) + +/** + * Check whether the given object has [[ProxyHandler]] and [[ProxyTarger]] internal slots + * + * @param obj_p ecma-object + */ +#if JERRY_BUILTIN_PROXY +#define ECMA_OBJECT_IS_PROXY(obj_p) (ECMA_OBJECT_TYPE_IS_PROXY (ecma_get_object_type ((obj_p)))) +#else /* !JERRY_BUILTIN_PROXY */ +#define ECMA_OBJECT_IS_PROXY(obj_p) (false) +#endif /* JERRY_BUILTIN_PROXY */ + +/* ecma-helpers-value.c */ +ecma_type_t JERRY_ATTR_CONST ecma_get_value_type_field (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_direct (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_simple (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_empty (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_undefined (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_null (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_boolean (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_true (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_false (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_found (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_array_hole (ecma_value_t value); + +bool JERRY_ATTR_CONST ecma_is_value_integer_number (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_are_values_integer_numbers (ecma_value_t first_value, ecma_value_t second_value); +bool JERRY_ATTR_CONST ecma_is_value_float_number (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_number (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_string (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_symbol (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_magic_string (ecma_value_t value, lit_magic_string_id_t id); +bool JERRY_ATTR_CONST ecma_is_value_bigint (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_prop_name (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_direct_string (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_non_direct_string (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_object (ecma_value_t value); +bool JERRY_ATTR_CONST ecma_is_value_exception (ecma_value_t value); +ecma_value_t ecma_is_value_array (ecma_value_t arg); + +void ecma_check_value_type_is_spec_defined (ecma_value_t value); + +ecma_value_t JERRY_ATTR_CONST ecma_make_boolean_value (bool boolean_value); +ecma_value_t JERRY_ATTR_CONST ecma_make_integer_value (ecma_integer_value_t integer_value); +ecma_value_t ecma_make_nan_value (void); +ecma_value_t ecma_make_float_value (ecma_number_t *ecma_num_p); +ecma_value_t ecma_make_length_value (ecma_length_t length); +ecma_value_t ecma_make_number_value (ecma_number_t ecma_number); +ecma_value_t ecma_make_int32_value (int32_t int32_number); +ecma_value_t ecma_make_uint32_value (uint32_t uint32_number); +ecma_value_t JERRY_ATTR_PURE ecma_make_string_value (const ecma_string_t *ecma_string_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_magic_string_value (lit_magic_string_id_t id); +ecma_value_t JERRY_ATTR_PURE ecma_make_object_value (const ecma_object_t *object_p); +ecma_value_t JERRY_ATTR_PURE ecma_make_extended_primitive_value (const ecma_extended_primitive_t *primitve_p, + uint32_t type); +ecma_integer_value_t JERRY_ATTR_CONST ecma_get_integer_from_value (ecma_value_t value); +ecma_number_t JERRY_ATTR_PURE ecma_get_float_from_value (ecma_value_t value); +ecma_number_t *ecma_get_pointer_from_float_value (ecma_value_t value); +ecma_number_t JERRY_ATTR_PURE ecma_get_number_from_value (ecma_value_t value); +ecma_string_t JERRY_ATTR_PURE *ecma_get_string_from_value (ecma_value_t value); +ecma_string_t JERRY_ATTR_PURE *ecma_get_symbol_from_value (ecma_value_t value); +ecma_string_t JERRY_ATTR_PURE *ecma_get_prop_name_from_value (ecma_value_t value); +ecma_object_t JERRY_ATTR_PURE *ecma_get_object_from_value (ecma_value_t value); +ecma_extended_primitive_t JERRY_ATTR_PURE *ecma_get_extended_primitive_from_value (ecma_value_t value); +ecma_value_t JERRY_ATTR_CONST ecma_invert_boolean_value (ecma_value_t value); +ecma_value_t ecma_copy_value (ecma_value_t value); +ecma_value_t ecma_fast_copy_value (ecma_value_t value); +ecma_value_t ecma_copy_value_if_not_object (ecma_value_t value); +void ecma_ref_if_object (ecma_value_t value); +void ecma_deref_if_object (ecma_value_t value); +ecma_value_t ecma_update_float_number (ecma_value_t float_value, ecma_number_t new_number); +void ecma_value_assign_value (ecma_value_t *value_p, ecma_value_t ecma_value); +void ecma_value_assign_number (ecma_value_t *value_p, ecma_number_t ecma_number); +void ecma_free_value (ecma_value_t value); +void ecma_fast_free_value (ecma_value_t value); +void ecma_free_value_if_not_object (ecma_value_t value); +void ecma_free_object (ecma_value_t value); +void ecma_free_number (ecma_value_t value); +lit_magic_string_id_t ecma_get_typeof_lit_id (ecma_value_t value); + +/* ecma-helpers-string.c */ +ecma_string_t *ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc); +bool ecma_prop_name_is_symbol (ecma_string_t *string_p); +ecma_length_t ecma_op_advance_string_index (ecma_string_t *str_p, ecma_length_t index_num, bool is_unicode); +#if JERRY_BUILTIN_CONTAINER +ecma_string_t *ecma_new_map_key_string (ecma_value_t value); +bool ecma_prop_name_is_map_key (ecma_string_t *string_p); +#endif /* JERRY_BUILTIN_CONTAINER */ +ecma_string_t *ecma_new_ecma_string_from_ascii (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +ecma_string_t *ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p, + lit_utf8_size_t string_size); +ecma_string_t * +ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size, void *user_p); +ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit); +ecma_string_t *ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, ecma_char_t second_code_unit); +ecma_string_t *ecma_new_ecma_string_from_length (ecma_length_t index); +ecma_string_t *ecma_new_ecma_string_from_uint32 (uint32_t uint32_number); +ecma_string_t *ecma_new_non_direct_string_from_uint32 (uint32_t uint32_number); +ecma_string_t *ecma_get_ecma_string_from_uint32 (uint32_t uint32_number); +ecma_string_t *ecma_new_ecma_string_from_number (ecma_number_t num); +ecma_string_t *ecma_get_magic_string (lit_magic_string_id_t id); +ecma_string_t *ecma_get_internal_string (lit_magic_string_id_t id); +ecma_string_t *ecma_append_chars_to_string (ecma_string_t *string1_p, + const lit_utf8_byte_t *cesu8_string2_p, + lit_utf8_size_t cesu8_string2_size, + lit_utf8_size_t cesu8_string2_length); +ecma_string_t *ecma_concat_ecma_strings (ecma_string_t *string1_p, ecma_string_t *string2_p); +void ecma_ref_ecma_string (ecma_string_t *string_p); +void ecma_ref_ecma_string_non_direct (ecma_string_t *string_p); +void ecma_deref_ecma_string (ecma_string_t *string_p); +void ecma_deref_ecma_string_non_direct (ecma_string_t *string_p); +void ecma_destroy_ecma_string (ecma_string_t *string_p); +ecma_number_t ecma_string_to_number (const ecma_string_t *str_p); +uint32_t ecma_string_get_array_index (const ecma_string_t *str_p); + +lit_utf8_size_t JERRY_ATTR_WARN_UNUSED_RESULT ecma_string_copy_to_buffer (const ecma_string_t *string_desc_p, + lit_utf8_byte_t *buffer_p, + lit_utf8_size_t buffer_size, + jerry_encoding_t encoding); +void +ecma_string_to_cesu8_bytes (const ecma_string_t *string_desc_p, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); +const lit_utf8_byte_t *ecma_string_get_chars (const ecma_string_t *string_p, + lit_utf8_size_t *size_p, + lit_utf8_size_t *length_p, + lit_utf8_byte_t *uint32_buff_p, + uint8_t *flags_p); +bool ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, lit_magic_string_id_t id); +bool ecma_string_is_empty (const ecma_string_t *string_p); +bool ecma_string_is_length (const ecma_string_t *string_p); + +jmem_cpointer_t ecma_string_to_property_name (ecma_string_t *prop_name_p, ecma_property_t *name_type_p); +ecma_string_t *ecma_string_from_property_name (ecma_property_t property, jmem_cpointer_t prop_name_cp); +lit_string_hash_t ecma_string_get_property_name_hash (ecma_property_t property, jmem_cpointer_t prop_name_cp); +uint32_t ecma_string_get_property_index (ecma_property_t property, jmem_cpointer_t prop_name_cp); +bool ecma_string_compare_to_property_name (ecma_property_t property, + jmem_cpointer_t prop_name_cp, + const ecma_string_t *string_p); + +bool ecma_compare_ecma_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p); +bool ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p); +bool ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, const ecma_string_t *string2_p); +lit_utf8_size_t ecma_string_get_length (const ecma_string_t *string_p); +lit_utf8_size_t ecma_string_get_utf8_length (const ecma_string_t *string_p); +lit_utf8_size_t ecma_string_get_size (const ecma_string_t *string_p); +lit_utf8_size_t ecma_string_get_utf8_size (const ecma_string_t *string_p); +ecma_char_t ecma_string_get_char_at_pos (const ecma_string_t *string_p, lit_utf8_size_t index); + +lit_magic_string_id_t ecma_get_string_magic (const ecma_string_t *string_p); + +lit_string_hash_t ecma_string_hash (const ecma_string_t *string_p); +ecma_string_t *ecma_string_substr (const ecma_string_t *string_p, lit_utf8_size_t start_pos, lit_utf8_size_t end_pos); +const lit_utf8_byte_t *ecma_string_trim_front (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p); +const lit_utf8_byte_t *ecma_string_trim_back (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p); +void ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p, lit_utf8_size_t *utf8_str_size); +ecma_string_t *ecma_string_trim (const ecma_string_t *string_p); +ecma_value_t +ecma_string_pad (ecma_value_t original_string_p, ecma_value_t max_length, ecma_value_t fill_string, bool pad_on_start); + +ecma_stringbuilder_t ecma_stringbuilder_create (void); +ecma_stringbuilder_t ecma_stringbuilder_create_from (ecma_string_t *string_p); +ecma_stringbuilder_t ecma_stringbuilder_create_raw (const lit_utf8_byte_t *data_p, const lit_utf8_size_t data_size); +lit_utf8_size_t ecma_stringbuilder_get_size (ecma_stringbuilder_t *builder_p); +lit_utf8_byte_t *ecma_stringbuilder_get_data (ecma_stringbuilder_t *builder_p); +void ecma_stringbuilder_revert (ecma_stringbuilder_t *builder_p, const lit_utf8_size_t size); +void ecma_stringbuilder_append (ecma_stringbuilder_t *builder_p, const ecma_string_t *string_p); +void ecma_stringbuilder_append_magic (ecma_stringbuilder_t *builder_p, const lit_magic_string_id_t id); +void ecma_stringbuilder_append_raw (ecma_stringbuilder_t *builder_p, + const lit_utf8_byte_t *data_p, + const lit_utf8_size_t data_size); +void ecma_stringbuilder_append_codepoint (ecma_stringbuilder_t *builder_p, lit_code_point_t cp); +void ecma_stringbuilder_append_char (ecma_stringbuilder_t *builder_p, const ecma_char_t c); +void ecma_stringbuilder_append_byte (ecma_stringbuilder_t *builder_p, const lit_utf8_byte_t); +ecma_string_t *ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p); +void ecma_stringbuilder_destroy (ecma_stringbuilder_t *builder_p); + +/* ecma-helpers-number.c */ +ecma_number_t ecma_number_make_nan (void); +ecma_number_t ecma_number_make_infinity (bool sign); +bool ecma_number_is_nan (ecma_number_t num); +bool ecma_number_is_negative (ecma_number_t num); +bool ecma_number_is_zero (ecma_number_t num); +bool ecma_number_is_infinity (ecma_number_t num); +bool ecma_number_is_finite (ecma_number_t num); +ecma_number_t ecma_number_get_prev (ecma_number_t num); +ecma_number_t ecma_number_get_next (ecma_number_t num); +ecma_number_t ecma_number_trunc (ecma_number_t num); +ecma_number_t ecma_number_remainder (ecma_number_t left_num, ecma_number_t right_num); +ecma_number_t ecma_number_pow (ecma_number_t x, ecma_number_t y); +ecma_value_t +ecma_number_parse_int (const lit_utf8_byte_t *string_buff, lit_utf8_size_t string_buff_size, ecma_value_t radix); +ecma_value_t ecma_number_parse_float (const lit_utf8_byte_t *string_buff, lit_utf8_size_t string_buff_size); +ecma_value_t ecma_integer_multiply (ecma_integer_value_t left_integer, ecma_integer_value_t right_integer); +lit_utf8_size_t ecma_number_to_decimal (ecma_number_t num, lit_utf8_byte_t *out_digits_p, int32_t *out_decimal_exp_p); + +/* ecma-helpers-collection.c */ +ecma_collection_t *ecma_new_collection (void); +void ecma_collection_push_back (ecma_collection_t *collection_p, ecma_value_t value); +void ecma_collection_reserve (ecma_collection_t *collection_p, uint32_t count); +void ecma_collection_append (ecma_collection_t *collection_p, const ecma_value_t *buffer_p, uint32_t count); +void ecma_collection_destroy (ecma_collection_t *collection_p); +void ecma_collection_free (ecma_collection_t *collection_p); +void ecma_collection_free_if_not_object (ecma_collection_t *collection_p); +void ecma_collection_free_objects (ecma_collection_t *collection_p); +void ecma_collection_free_template_literal (ecma_collection_t *collection_p); +bool ecma_collection_check_duplicated_entries (ecma_collection_t *collection_p); +bool ecma_collection_has_string_value (ecma_collection_t *collection_p, ecma_string_t *string_p); + +ecma_value_t *ecma_new_compact_collection (void); +ecma_value_t *ecma_compact_collection_push_back (ecma_value_t *compact_collection_p, ecma_value_t value); +ecma_value_t *ecma_compact_collection_shrink (ecma_value_t *compact_collection_p); +void ecma_compact_collection_free (ecma_value_t *compact_collection_p); +ecma_value_t *ecma_compact_collection_end (ecma_value_t *compact_collection_p); +void ecma_compact_collection_destroy (ecma_value_t *compact_collection_p); + +/* ecma-helpers.c */ +ecma_object_t *ecma_create_object (ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type); +ecma_object_t *ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p); +ecma_object_t *ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, ecma_object_t *binding_obj_p); +ecma_object_t *ecma_create_lex_env_class (ecma_object_t *outer_lexical_environment_p, size_t lexical_env_size); +bool JERRY_ATTR_PURE ecma_is_lexical_environment (const ecma_object_t *object_p); +void ecma_op_ordinary_object_set_extensible (ecma_object_t *object_p); +ecma_object_type_t JERRY_ATTR_PURE ecma_get_object_type (const ecma_object_t *object_p); +ecma_object_base_type_t JERRY_ATTR_PURE ecma_get_object_base_type (const ecma_object_t *object_p); +bool JERRY_ATTR_PURE ecma_object_class_is (ecma_object_t *object_p, ecma_object_class_type_t class_id); +ecma_lexical_environment_type_t JERRY_ATTR_PURE ecma_get_lex_env_type (const ecma_object_t *object_p); +ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_binding_object (const ecma_object_t *object_p); +ecma_object_t *ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, bool copy_values); + +ecma_property_value_t *ecma_create_named_data_property (ecma_object_t *object_p, + ecma_string_t *name_p, + uint8_t prop_attributes, + ecma_property_t **out_prop_p); +ecma_property_value_t *ecma_create_named_accessor_property (ecma_object_t *object_p, + ecma_string_t *name_p, + ecma_object_t *get_p, + ecma_object_t *set_p, + uint8_t prop_attributes, + ecma_property_t **out_prop_p); +#if JERRY_MODULE_SYSTEM +void ecma_create_named_reference_property (ecma_object_t *object_p, ecma_string_t *name_p, ecma_value_t reference); +#endif /* JERRY_MODULE_SYSTEM */ +ecma_property_t *ecma_find_named_property (ecma_object_t *obj_p, ecma_string_t *name_p); +ecma_property_value_t *ecma_get_named_data_property (ecma_object_t *obj_p, ecma_string_t *name_p); + +void ecma_delete_property (ecma_object_t *object_p, ecma_property_value_t *prop_value_p); + +void +ecma_named_data_property_assign_value (ecma_object_t *obj_p, ecma_property_value_t *prop_value_p, ecma_value_t value); + +ecma_getter_setter_pointers_t *ecma_get_named_accessor_property (const ecma_property_value_t *prop_value_p); +void ecma_set_named_accessor_property_getter (ecma_object_t *object_p, + ecma_property_value_t *prop_value_p, + ecma_object_t *getter_p); +void ecma_set_named_accessor_property_setter (ecma_object_t *object_p, + ecma_property_value_t *prop_value_p, + ecma_object_t *setter_p); +#if JERRY_MODULE_SYSTEM +ecma_value_t ecma_property_to_reference (ecma_property_t *property_p); +ecma_property_value_t *ecma_get_property_value_from_named_reference (ecma_property_value_t *reference_p); +#endif /* JERRY_MODULE_SYSTEM */ +bool ecma_is_property_writable (ecma_property_t property); +void ecma_set_property_writable_attr (ecma_property_t *property_p, bool is_writable); +bool ecma_is_property_enumerable (ecma_property_t property); +void ecma_set_property_enumerable_attr (ecma_property_t *property_p, bool is_enumerable); +bool ecma_is_property_configurable (ecma_property_t property); +void ecma_set_property_configurable_attr (ecma_property_t *property_p, bool is_configurable); + +#if JERRY_LCACHE +bool ecma_is_property_lcached (ecma_property_t *property_p); +void ecma_set_property_lcached (ecma_property_t *property_p, bool is_lcached); +#endif /* JERRY_LCACHE */ + +ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); +void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p); + +void ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p); +void ecma_deref_exception (ecma_extended_primitive_t *exception_p); +#if JERRY_BUILTIN_BIGINT +void ecma_deref_bigint (ecma_extended_primitive_t *bigint_p); +#endif /* JERRY_BUILTIN_BIGINT */ + +ecma_value_t ecma_create_exception (ecma_value_t value, uint32_t options); +ecma_value_t ecma_create_exception_from_context (void); +ecma_value_t ecma_create_exception_from_object (ecma_object_t *object_p); +void ecma_throw_exception (ecma_value_t value); + +void ecma_script_deref (ecma_value_t script_value); +void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p); +void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p); +ecma_value_t ecma_script_get_from_value (ecma_value_t value); +ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p); +ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p); +ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p); +#if JERRY_LINE_INFO +uint8_t *ecma_compiled_code_get_line_info (const ecma_compiled_code_t *bytecode_header_p); +#endif /* JERRY_LINE_INFO */ +ecma_value_t ecma_get_source_name (const ecma_compiled_code_t *bytecode_p); +#if (JERRY_STACK_LIMIT != 0) +uintptr_t ecma_get_current_stack_usage (void); +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/* ecma-helpers-external-pointers.c */ +bool ecma_create_native_pointer_property (ecma_object_t *obj_p, + void *native_p, + const jerry_object_native_info_t *native_info_p); +ecma_native_pointer_t *ecma_get_native_pointer_value (ecma_object_t *obj_p, + const jerry_object_native_info_t *native_info_p); +bool ecma_delete_native_pointer_property (ecma_object_t *obj_p, const jerry_object_native_info_t *native_info_p); + +/* ecma-helpers-conversion.c */ +ecma_number_t ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, lit_utf8_size_t str_size, uint32_t option); +ecma_number_t ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, + lit_utf8_size_t str_size, + uint32_t radix, + uint32_t option); +lit_utf8_size_t ecma_uint32_to_utf8_string (uint32_t value, lit_utf8_byte_t *out_buffer_p, lit_utf8_size_t buffer_size); +uint32_t ecma_number_to_uint32 (ecma_number_t num); +int32_t ecma_number_to_int32 (ecma_number_t num); +lit_utf8_size_t ecma_number_to_utf8_string (ecma_number_t num, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); + +/* ecma-helpers-errol.c */ +lit_utf8_size_t ecma_errol0_dtoa (double val, lit_utf8_byte_t *buffer_p, int32_t *exp_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.cpp new file mode 100644 index 00000000..60a3b2e0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.cpp @@ -0,0 +1,106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-init-finalize.h" + +#include "ecma-builtins.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-literal-storage.h" + +#include "jcontext.h" +#include "jmem.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmainitfinalize Initialization and finalization of ECMA components + * @{ + */ + +/** + * Maximum number of GC loops on cleanup. + */ +#define JERRY_GC_LOOP_LIMIT 100 + +/** + * Initialize ECMA components + */ +void +ecma_init (void) +{ +#if (JERRY_GC_MARK_LIMIT != 0) + JERRY_CONTEXT (ecma_gc_mark_recursion_limit) = JERRY_GC_MARK_LIMIT; +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + + ecma_init_global_environment (); + +#if JERRY_PROPERTY_HASHMAP + JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) = ECMA_PROP_HASHMAP_ALLOC_ON; + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_HIGH_PRESSURE_GC; +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if (JERRY_STACK_LIMIT != 0) + volatile int sp; + JERRY_CONTEXT (stack_base) = (uintptr_t) &sp; +#endif /* (JERRY_STACK_LIMIT != 0) */ + + ecma_job_queue_init (); + + JERRY_CONTEXT (current_new_target_p) = NULL; + +#if JERRY_BUILTIN_TYPEDARRAY + JERRY_CONTEXT (arraybuffer_compact_allocation_limit) = 256; +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +} /* ecma_init */ + +/** + * Finalize ECMA components + */ +void +ecma_finalize (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) == NULL); + + ecma_finalize_global_environment (); + uint8_t runs = 0; + + do + { + ecma_gc_run (); + if (++runs >= JERRY_GC_LOOP_LIMIT) + { + jerry_fatal (JERRY_FATAL_UNTERMINATED_GC_LOOPS); + } + } while (JERRY_CONTEXT (ecma_gc_new_objects) != 0); + + jmem_cpointer_t *global_symbols_cp = JERRY_CONTEXT (global_symbols_cp); + + for (uint32_t i = 0; i < ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT; i++) + { + if (global_symbols_cp[i] != JMEM_CP_NULL) + { + ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, global_symbols_cp[i])); + } + } + + ecma_finalize_lit_storage (); +} /* ecma_finalize */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h new file mode 100644 index 00000000..0e4fda21 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-init-finalize.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_INIT_FINALIZE_H +#define ECMA_INIT_FINALIZE_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmainitfinalize Initialization and finalization of ECMA components + * @{ + */ + +void ecma_init (void); +void ecma_finalize (void); + +/** + * @} + * @} + */ + +#endif /* !ECMA_INIT_FINALIZE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.cpp new file mode 100644 index 00000000..e6a87388 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.cpp @@ -0,0 +1,221 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-lcache.h" + +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalcache Property lookup cache + * @{ + */ + +#if JERRY_LCACHE + +/** + * Bitshift index for calculating hash. + */ +#if JERRY_CPOINTER_32_BIT +#define ECMA_LCACHE_HASH_BITSHIFT_INDEX (2 * JMEM_ALIGNMENT_LOG) +#else /* !JERRY_CPOINTER_32_BIT */ +#define ECMA_LCACHE_HASH_BITSHIFT_INDEX 0 +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Mask for hash bits + */ +#define ECMA_LCACHE_HASH_MASK ((ECMA_LCACHE_HASH_ROWS_COUNT - 1) << ECMA_LCACHE_HASH_BITSHIFT_INDEX) + +/** + * Bitshift index for creating property identifier + */ +#define ECMA_LCACHE_HASH_ENTRY_ID_SHIFT (8 * sizeof (jmem_cpointer_t)) + +/** + * Create property identifier + */ +#define ECMA_LCACHE_CREATE_ID(object_cp, name_cp) \ + (((ecma_lcache_hash_entry_id_t) (object_cp) << ECMA_LCACHE_HASH_ENTRY_ID_SHIFT) | (name_cp)) + +/** + * Invalidate specified LCache entry + */ +static inline void +ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to invalidate */ +{ + JERRY_ASSERT (entry_p != NULL); + JERRY_ASSERT (entry_p->id != 0); + JERRY_ASSERT (entry_p->prop_p != NULL); + + entry_p->id = 0; + ecma_set_property_lcached (entry_p->prop_p, false); +} /* ecma_lcache_invalidate_entry */ + +/** + * Compute the row index of object / property name pair + * + * @return row index + */ +static inline size_t +ecma_lcache_row_index (jmem_cpointer_t object_cp, /**< compressed pointer to object */ + jmem_cpointer_t name_cp) /**< compressed pointer to property name */ +{ + /* Randomize the property name with the object pointer using a xor operation, + * so properties of different objects with the same name can be cached effectively. */ + return (size_t) (((name_cp ^ object_cp) & ECMA_LCACHE_HASH_MASK) >> ECMA_LCACHE_HASH_BITSHIFT_INDEX); +} /* ecma_lcache_row_index */ + +/** + * Insert an entry into LCache + */ +void +ecma_lcache_insert (const ecma_object_t *object_p, /**< object */ + const jmem_cpointer_t name_cp, /**< property name */ + ecma_property_t *prop_p) /**< property */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (prop_p != NULL && !ecma_is_property_lcached (prop_p)); + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*prop_p)); + + jmem_cpointer_t object_cp; + + ECMA_SET_NON_NULL_POINTER (object_cp, object_p); + + size_t row_index = ecma_lcache_row_index (object_cp, name_cp); + ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache)[row_index]; + ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH; + + do + { + if (entry_p->id == 0) + { + goto insert; + } + + entry_p++; + } while (entry_p < entry_end_p); + + /* Invalidate the last entry. */ + ecma_lcache_invalidate_entry (--entry_p); + + /* Shift other entries towards the end. */ + for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH - 1; i++) + { + entry_p->id = entry_p[-1].id; + entry_p->prop_p = entry_p[-1].prop_p; + entry_p--; + } + +insert: + entry_p->prop_p = prop_p; + entry_p->id = ECMA_LCACHE_CREATE_ID (object_cp, name_cp); + + ecma_set_property_lcached (entry_p->prop_p, true); +} /* ecma_lcache_insert */ + +/** + * Lookup property in the LCache + * + * @return a pointer to an ecma_property_t if the lookup is successful + * NULL otherwise + */ +ecma_property_t * +ecma_lcache_lookup (const ecma_object_t *object_p, /**< object */ + const ecma_string_t *prop_name_p) /**< property's name */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (prop_name_p != NULL); + + jmem_cpointer_t object_cp; + ECMA_SET_NON_NULL_POINTER (object_cp, object_p); + + ecma_property_t prop_name_type = ECMA_DIRECT_STRING_PTR; + jmem_cpointer_t prop_name_cp; + + if (JERRY_UNLIKELY (ECMA_IS_DIRECT_STRING (prop_name_p))) + { + prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (prop_name_p); + prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); + } + else + { + ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); + } + + size_t row_index = ecma_lcache_row_index (object_cp, prop_name_cp); + + ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache)[row_index]; + ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH; + ecma_lcache_hash_entry_id_t id = ECMA_LCACHE_CREATE_ID (object_cp, prop_name_cp); + + do + { + if (entry_p->id == id && JERRY_LIKELY (ECMA_PROPERTY_GET_NAME_TYPE (*entry_p->prop_p) == prop_name_type)) + { + JERRY_ASSERT (entry_p->prop_p != NULL && ecma_is_property_lcached (entry_p->prop_p)); + return entry_p->prop_p; + } + entry_p++; + } while (entry_p < entry_end_p); + + return NULL; +} /* ecma_lcache_lookup */ + +/** + * Invalidate LCache entries associated with given object and property name / property + */ +void +ecma_lcache_invalidate (const ecma_object_t *object_p, /**< object */ + const jmem_cpointer_t name_cp, /**< property name */ + ecma_property_t *prop_p) /**< property */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p)); + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*prop_p)); + + jmem_cpointer_t object_cp; + ECMA_SET_NON_NULL_POINTER (object_cp, object_p); + + size_t row_index = ecma_lcache_row_index (object_cp, name_cp); + ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache)[row_index]; + + while (true) + { + /* The property must be present. */ + JERRY_ASSERT (entry_p - JERRY_CONTEXT (lcache)[row_index] < ECMA_LCACHE_HASH_ROW_LENGTH); + + if (entry_p->id != 0 && entry_p->prop_p == prop_p) + { + JERRY_ASSERT (entry_p->id == ECMA_LCACHE_CREATE_ID (object_cp, name_cp)); + + ecma_lcache_invalidate_entry (entry_p); + return; + } + entry_p++; + } +} /* ecma_lcache_invalidate */ + +#endif /* JERRY_LCACHE */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.h new file mode 100644 index 00000000..818e410b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-lcache.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LCACHE_H +#define ECMA_LCACHE_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalcache Property lookup cache + * @{ + */ + +#include "ecma-globals.h" + +#if JERRY_LCACHE +void ecma_lcache_insert (const ecma_object_t *object_p, const jmem_cpointer_t name_cp, ecma_property_t *prop_p); +ecma_property_t *ecma_lcache_lookup (const ecma_object_t *object_p, const ecma_string_t *prop_name_p); +void ecma_lcache_invalidate (const ecma_object_t *object_p, const jmem_cpointer_t name_cp, ecma_property_t *prop_p); + +#endif /* JERRY_LCACHE */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_LCACHE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.cpp new file mode 100644 index 00000000..48760e84 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.cpp @@ -0,0 +1,271 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-line-info.h" + +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalineinfo Line info + * @{ + */ + +#if JERRY_LINE_INFO + +/* The layout of the structure is defined in js-parser-line-info-create.c */ + +JERRY_STATIC_ASSERT ((ECMA_LINE_INFO_COLUMN_DEFAULT - 1) == ((ECMA_LINE_INFO_ENCODE_TWO_BYTE >> 1) - 1), + ecma_line_info_column_1_must_be_accessible_with_the_highest_one_byte_negative_value); + +/** + * Decodes an uint32_t number, and updates the buffer position. + * Numbers expected to be larger values. + * + * @return the decoded value + */ +uint32_t +ecma_line_info_decode_vlq (uint8_t **buffer_p) /**< [in/out] target buffer */ +{ + uint8_t *source_p = *buffer_p; + uint32_t value = 0; + + do + { + value = (value << ECMA_LINE_INFO_VLQ_SHIFT) | (*source_p & ECMA_LINE_INFO_VLQ_MASK); + } while (*source_p++ & ECMA_LINE_INFO_VLQ_CONTINUE); + + *buffer_p = source_p; + return value; +} /* ecma_line_info_decode_vlq */ + +/** + * Decodes an uint32_t number, and updates the buffer position. + * Numbers expected to be smaller values. + * + * @return the decoded value + */ +static uint32_t +ecma_line_info_decode_small (uint8_t **buffer_p) /**< [in/out] target buffer */ +{ + uint8_t *source_p = *buffer_p; + uint32_t type = source_p[0]; + + *buffer_p = source_p + 1; + + if (type < ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN) + { + return type; + } + + if (type == ECMA_LINE_INFO_ENCODE_TWO_BYTE) + { + *buffer_p = source_p + 2; + return ((uint32_t) source_p[1]) + ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN; + } + + JERRY_ASSERT (type == ECMA_LINE_INFO_ENCODE_VLQ); + return ecma_line_info_decode_vlq (buffer_p) + ECMA_LINE_INFO_ENCODE_VLQ_MIN; +} /* ecma_line_info_decode_small */ + +/** + * Updates a value using an encoded difference. + * + * @return updated value + */ +uint32_t +ecma_line_info_difference_update (uint32_t current_value, /**< current value */ + uint32_t difference_value) /**< encoded difference */ +{ + if ((difference_value & 0x1) == ECMA_LINE_INFO_INCREASE) + { + return current_value + (difference_value >> 1) + 1; + } + + return current_value - (difference_value >> 1); +} /* ecma_line_info_difference_update */ + +/** + * Release line info data. + */ +void +ecma_line_info_free (uint8_t *line_info_p) /**< line info buffer */ +{ + uint8_t *source_p = line_info_p; + uint32_t total_length = ecma_line_info_decode_vlq (&source_p); + + jmem_heap_free_block (line_info_p, total_length + (uint32_t) (source_p - line_info_p)); +} /* ecma_line_info_free */ + +/** + * Returns the line/column information for a given byte code offset. + */ +void +ecma_line_info_get (uint8_t *line_info_p, /**< line info buffer */ + uint32_t offset, /**< byte code offset */ + jerry_frame_location_t *location_p) /**< [out] location */ +{ + uint32_t line = 1; + uint32_t column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t end_offset = 0; + uint32_t end_offset_increase; + uint32_t value; + + /* Skip total_length. */ + ecma_line_info_decode_vlq (&line_info_p); + + while (true) + { + value = ecma_line_info_decode_vlq (&line_info_p); + line = ecma_line_info_difference_update (line, value); + + if (*line_info_p == 0) + { + break; + } + + uint8_t *size_p = line_info_p + *line_info_p + (ECMA_LINE_INFO_STREAM_SIZE_MIN + 1); + + uint32_t next_end_offset = end_offset + ecma_line_info_decode_vlq (&size_p); + + if (offset < next_end_offset) + { + break; + } + + end_offset = next_end_offset; + line_info_p = size_p; + } + + line_info_p++; + + do + { + end_offset_increase = ecma_line_info_decode_small (&line_info_p); + + if (end_offset_increase & ECMA_LINE_INFO_HAS_LINE) + { + value = ecma_line_info_decode_small (&line_info_p); + line = ecma_line_info_difference_update (line, value); + column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + end_offset_increase >>= 1; + + value = ecma_line_info_decode_small (&line_info_p); + column = ecma_line_info_difference_update (column, value); + + end_offset += end_offset_increase; + } while (end_offset_increase != 0 && end_offset <= offset); + + location_p->line = line; + location_p->column = column; +} /* ecma_line_info_get */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Dumps line info data. + */ +void +ecma_line_info_dump (uint8_t *line_info_p) /**< dumps line info data */ +{ + bool block_last = false; + uint32_t block_line = 1; + uint32_t block_byte_code_offset = 0; + uint32_t value; + + value = ecma_line_info_decode_vlq (&line_info_p); + JERRY_DEBUG_MSG ("\nLine info size: %d bytes\n", (int) value); + + while (true) + { + value = ecma_line_info_decode_vlq (&line_info_p); + block_line = ecma_line_info_difference_update (block_line, value); + + JERRY_DEBUG_MSG ("\nNew block: line: %d", (int) block_line); + + if (*line_info_p == 0) + { + JERRY_DEBUG_MSG (" StreamLength: [last]\n"); + block_last = true; + } + else + { + uint8_t *size_p = line_info_p + *line_info_p + (ECMA_LINE_INFO_STREAM_SIZE_MIN + 1); + + value = ecma_line_info_decode_vlq (&size_p); + + JERRY_DEBUG_MSG (" StreamLength: %d ByteCodeSize: %d\n", + (int) (*line_info_p + ECMA_LINE_INFO_STREAM_SIZE_MIN), + (int) value); + } + + line_info_p++; + + uint32_t stream_line = block_line; + uint32_t stream_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t stream_end_offset = block_byte_code_offset; + + while (true) + { + uint32_t stream_end_offset_increase = ecma_line_info_decode_small (&line_info_p); + + if (stream_end_offset_increase & ECMA_LINE_INFO_HAS_LINE) + { + value = ecma_line_info_decode_small (&line_info_p); + stream_line = ecma_line_info_difference_update (stream_line, value); + stream_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + stream_end_offset_increase >>= 1; + + value = ecma_line_info_decode_small (&line_info_p); + stream_column = ecma_line_info_difference_update (stream_column, value); + + if (stream_end_offset_increase == 0) + { + JERRY_DEBUG_MSG (" ByteCodeEndOffset: [unterminated] Line: %d Column: %d\n", + (int) stream_line, + (int) stream_column); + break; + } + + stream_end_offset += stream_end_offset_increase; + + JERRY_DEBUG_MSG (" ByteCodeEndOffset: %d Line: %d Column: %d\n", + (int) stream_end_offset, + (int) stream_line, + (int) stream_column); + } + + if (block_last) + { + break; + } + + block_byte_code_offset += ecma_line_info_decode_vlq (&line_info_p); + } +} /* ecma_line_info_dump */ + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +#endif /* JERRY_LINE_INFO */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.h new file mode 100644 index 00000000..2e1cbe0e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-line-info.h @@ -0,0 +1,114 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LINE_INFO_H +#define ECMA_LINE_INFO_H + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalineinfo Line info + * @{ + */ + +#ifdef JERRY_LINE_INFO + +#include "ecma-globals.h" + +/** + * Increase the current value of line or column. + */ +#define ECMA_LINE_INFO_INCREASE 0x0 + +/** + * Decrease the current value of line or column. + */ +#define ECMA_LINE_INFO_DECREASE 0x1 + +/** + * Line update is present. + */ +#define ECMA_LINE_INFO_HAS_LINE 0x1 + +/** + * A default value for columns after a line update. + */ +#define ECMA_LINE_INFO_COLUMN_DEFAULT 127 + +/** + * Vlq encoding: flag which is set for all bytes except the last one. + */ +#define ECMA_LINE_INFO_VLQ_CONTINUE 0x80 + +/** + * Vlq encoding: mask to decode the number fragment. + */ +#define ECMA_LINE_INFO_VLQ_MASK 0x7f + +/** + * Vlq encoding: number of bits stored in a byte. + */ +#define ECMA_LINE_INFO_VLQ_SHIFT 7 + +/** + * Small encoding: a value which represents a two byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_TWO_BYTE (UINT8_MAX - 1) + +/** + * Small encoding: minimum value of an encoded two byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN (UINT8_MAX - 1) + +/** + * Small encoding: a value which represents a three byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_VLQ UINT8_MAX + +/** + * Small encoding: minimum value of an encoded three byte long number. + */ +#define ECMA_LINE_INFO_ENCODE_VLQ_MIN (ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN + UINT8_MAX + 1) + +/** + * Maximum number of line/column entries stored in a stream. + */ +#define ECMA_LINE_INFO_STREAM_VALUE_COUNT_MAX 48 + +/** + * Minimum size of a stream (except the last one). + */ +#define ECMA_LINE_INFO_STREAM_SIZE_MIN ((2 * ECMA_LINE_INFO_STREAM_VALUE_COUNT_MAX) - 1) + +/* Helper functions for parser/js/js-parser-line-info-create.c. */ +uint32_t ecma_line_info_decode_vlq (uint8_t **buffer_p); +uint32_t ecma_line_info_difference_update (uint32_t current_value, uint32_t difference_value); + +/* General functions. */ +void ecma_line_info_free (uint8_t *line_info_p); +void ecma_line_info_get (uint8_t *line_info_p, uint32_t offset, jerry_frame_location_t *location_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE +void ecma_line_info_dump (uint8_t *line_info_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +#endif /* JERRY_LINE_INFO */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_LINE_INFO_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.cpp new file mode 100644 index 00000000..db086a51 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.cpp @@ -0,0 +1,741 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-literal-storage.h" + +#include "ecma-alloc.h" +#include "ecma-big-uint.h" +#include "ecma-bigint.h" +#include "ecma-helpers.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalitstorage Literal storage + * @{ + */ + +/** + * Free symbol list + */ +static void +ecma_free_symbol_list (jmem_cpointer_t symbol_list_cp) /**< symbol list */ +{ + while (symbol_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, symbol_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (symbol_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, symbol_list_p->values[i]); + + JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p)); + ecma_deref_ecma_string (string_p); + } + } + + jmem_cpointer_t next_item_cp = symbol_list_p->next_cp; + jmem_pools_free (symbol_list_p, sizeof (ecma_lit_storage_item_t)); + symbol_list_cp = next_item_cp; + } +} /* ecma_free_symbol_list */ + +/** + * Free string list + */ +static void +ecma_free_string_list (jmem_cpointer_t string_list_cp) /**< string list */ +{ + while (string_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (string_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, string_list_p->values[i]); + + JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p)); + ecma_destroy_ecma_string (string_p); + } + } + + jmem_cpointer_t next_item_cp = string_list_p->next_cp; + jmem_pools_free (string_list_p, sizeof (ecma_lit_storage_item_t)); + string_list_cp = next_item_cp; + } +} /* ecma_free_string_list */ + +/** + * Free number list + */ +static void +ecma_free_number_list (jmem_cpointer_t number_list_cp) /**< number list */ +{ + while (number_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, number_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (number_list_p->values[i] != JMEM_CP_NULL) + { + ecma_dealloc_number (JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t, number_list_p->values[i])); + } + } + + jmem_cpointer_t next_item_cp = number_list_p->next_cp; + jmem_pools_free (number_list_p, sizeof (ecma_lit_storage_item_t)); + number_list_cp = next_item_cp; + } +} /* ecma_free_number_list */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Free bigint list + */ +static void +ecma_free_bigint_list (jmem_cpointer_t bigint_list_cp) /**< bigint list */ +{ + while (bigint_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *bigint_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, bigint_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (bigint_list_p->values[i] != JMEM_CP_NULL) + { + ecma_extended_primitive_t *bigint_p = + JMEM_CP_GET_NON_NULL_POINTER (ecma_extended_primitive_t, bigint_list_p->values[i]); + JERRY_ASSERT (ECMA_EXTENDED_PRIMITIVE_IS_REF_EQUALS_TO_ONE (bigint_p)); + ecma_deref_bigint (bigint_p); + } + } + + jmem_cpointer_t next_item_cp = bigint_list_p->next_cp; + jmem_pools_free (bigint_list_p, sizeof (ecma_lit_storage_item_t)); + bigint_list_cp = next_item_cp; + } +} /* ecma_free_bigint_list */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Finalize literal storage + */ +void +ecma_finalize_lit_storage (void) +{ + ecma_free_symbol_list (JERRY_CONTEXT (symbol_list_first_cp)); + ecma_free_string_list (JERRY_CONTEXT (string_list_first_cp)); + ecma_free_number_list (JERRY_CONTEXT (number_list_first_cp)); +#if JERRY_BUILTIN_BIGINT + ecma_free_bigint_list (JERRY_CONTEXT (bigint_list_first_cp)); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* ecma_finalize_lit_storage */ + +/** + * Find or create a literal string. + * + * @return ecma_string_t compressed pointer + */ +ecma_value_t +ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string to be searched */ + lit_utf8_size_t size, /**< size of the string */ + bool is_ascii) /**< encode of the string */ +{ + ecma_string_t *string_p = + (is_ascii ? ecma_new_ecma_string_from_ascii (chars_p, size) : ecma_new_ecma_string_from_utf8 (chars_p, size)); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return ecma_make_string_value (string_p); + } + + jmem_cpointer_t string_list_cp = JERRY_CONTEXT (string_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (string_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (string_list_p->values[i] == JMEM_CP_NULL) + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = string_list_p->values + i; + } + } + else + { + ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, string_list_p->values[i]); + + if (ecma_compare_ecma_strings (string_p, value_p)) + { + /* Return with string if found in the list. */ + ecma_deref_ecma_string (string_p); + return ecma_make_string_value (value_p); + } + } + } + + string_list_cp = string_list_p->next_cp; + } + + ECMA_SET_STRING_AS_STATIC (string_p); + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, string_p); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return ecma_make_string_value (string_p); + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (string_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (string_list_first_cp), new_item_p); + + return ecma_make_string_value (string_p); +} /* ecma_find_or_create_literal_string */ + +/** + * Find or create a literal number. + * + * @return ecma value + */ +ecma_value_t +ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be searched */ +{ + ecma_value_t num = ecma_make_number_value (number_arg); + + if (ecma_is_value_integer_number (num)) + { + return num; + } + + JERRY_ASSERT (ecma_is_value_float_number (num)); + + jmem_cpointer_t number_list_cp = JERRY_CONTEXT (number_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (number_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, number_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (number_list_p->values[i] == JMEM_CP_NULL) + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = number_list_p->values + i; + } + } + else + { + ecma_number_t *number_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t, number_list_p->values[i]); + + if (*number_p == number_arg) + { + ecma_free_value (num); + return ecma_make_float_value (number_p); + } + } + } + + number_list_cp = number_list_p->next_cp; + } + + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, ecma_get_pointer_from_float_value (num)); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return num; + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (number_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (number_list_first_cp), new_item_p); + + return num; +} /* ecma_find_or_create_literal_number */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Find or create a literal BigInt. + * + * @return BigInt value + */ +ecma_value_t +ecma_find_or_create_literal_bigint (ecma_value_t bigint) /**< bigint to be searched */ +{ + JERRY_ASSERT (ecma_is_value_bigint (bigint)); + + if (bigint == ECMA_BIGINT_ZERO) + { + return bigint; + } + + jmem_cpointer_t bigint_list_cp = JERRY_CONTEXT (bigint_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (bigint_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *bigint_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, bigint_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (bigint_list_p->values[i] == JMEM_CP_NULL) + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = bigint_list_p->values + i; + } + } + else + { + ecma_extended_primitive_t *other_bigint_p = + JMEM_CP_GET_NON_NULL_POINTER (ecma_extended_primitive_t, bigint_list_p->values[i]); + ecma_value_t other_bigint = ecma_make_extended_primitive_value (other_bigint_p, ECMA_TYPE_BIGINT); + + if (ecma_bigint_is_equal_to_bigint (bigint, other_bigint)) + { + ecma_free_value (bigint); + return other_bigint; + } + } + } + + bigint_list_cp = bigint_list_p->next_cp; + } + + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, ecma_get_extended_primitive_from_value (bigint)); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return bigint; + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (bigint_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (bigint_list_first_cp), new_item_p); + + return bigint; +} /* ecma_find_or_create_literal_bigint */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Log2 of snapshot literal alignment. + */ +#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG 1 + +/** + * Snapshot literal alignment. + */ +#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT (1u << JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG) + +/** + * Literal offset shift. + */ +#define JERRY_SNAPSHOT_LITERAL_SHIFT (ECMA_VALUE_SHIFT + 2) + +/** + * Literal value is number. + */ +#define JERRY_SNAPSHOT_LITERAL_IS_NUMBER (1u << ECMA_VALUE_SHIFT) + +#if JERRY_BUILTIN_BIGINT +/** + * Literal value is BigInt. + */ +#define JERRY_SNAPSHOT_LITERAL_IS_BIGINT (2u << ECMA_VALUE_SHIFT) +#endif /* JERRY_BUILTIN_BIGINT */ + +#if JERRY_SNAPSHOT_SAVE + +/** + * Append the value at the end of the appropriate list if it is not present there. + */ +void +ecma_save_literals_append_value (ecma_value_t value, /**< value to be appended */ + ecma_collection_t *lit_pool_p) /**< list of known values */ +{ + /* Unlike direct numbers, direct strings are converted to character literals. */ + if (!ecma_is_value_string (value) +#if JERRY_BUILTIN_BIGINT + && (!ecma_is_value_bigint (value) || value == ECMA_BIGINT_ZERO) +#endif /* JERRY_BUILTIN_BIGINT */ + && !ecma_is_value_float_number (value)) + { + return; + } + + ecma_value_t *buffer_p = lit_pool_p->buffer_p; + + for (uint32_t i = 0; i < lit_pool_p->item_count; i++) + { + /* Strings / numbers are direct strings or stored in the literal storage. + * Therefore direct comparison is enough to find the same strings / numbers. */ + if (buffer_p[i] == value) + { + return; + } + } + + ecma_collection_push_back (lit_pool_p, value); +} /* ecma_save_literals_append_value */ + +/** + * Add names from a byte-code data to a list. + */ +void +ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, /**< byte-code data */ + ecma_collection_t *lit_pool_p) /**< list of known values */ +{ + ecma_value_t *literal_p; + uint32_t argument_end; + uint32_t register_end; + uint32_t const_literal_end; + uint32_t literal_end; + + JERRY_ASSERT (CBC_IS_FUNCTION (compiled_code_p->status_flags)); + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + uint8_t *byte_p = (uint8_t *) compiled_code_p; + + literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); + register_end = args_p->register_end; + const_literal_end = args_p->const_literal_end - register_end; + literal_end = args_p->literal_end - register_end; + argument_end = args_p->argument_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + uint8_t *byte_p = (uint8_t *) compiled_code_p; + + literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); + register_end = args_p->register_end; + const_literal_end = args_p->const_literal_end - register_end; + literal_end = args_p->literal_end - register_end; + argument_end = args_p->argument_end; + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + for (uint32_t i = 0; i < argument_end; i++) + { + ecma_save_literals_append_value (literal_p[i], lit_pool_p); + } + } + + for (uint32_t i = 0; i < const_literal_end; i++) + { + ecma_save_literals_append_value (literal_p[i], lit_pool_p); + } + + for (uint32_t i = const_literal_end; i < literal_end; i++) + { + ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, literal_p[i]); + + if (CBC_IS_FUNCTION (bytecode_p->status_flags) && bytecode_p != compiled_code_p) + { + ecma_save_literals_add_compiled_code (bytecode_p, lit_pool_p); + } + } + + uint8_t *byte_p = ((uint8_t *) compiled_code_p) + (((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG); + literal_p = ecma_snapshot_resolve_serializable_values ((ecma_compiled_code_t *) compiled_code_p, byte_p); + + while (literal_p < (ecma_value_t *) byte_p) + { + ecma_save_literals_append_value (*literal_p, lit_pool_p); + literal_p++; + } +} /* ecma_save_literals_add_compiled_code */ + +/** + * Save literals to specified snapshot buffer. + * + * Note: + * Frees 'lit_pool_p' regardless of success. + * + * @return true - if save was performed successfully (i.e. buffer size is sufficient), + * false - otherwise + */ +bool +ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, /**< list of known values */ + uint32_t *buffer_p, /**< [out] output snapshot buffer */ + size_t buffer_size, /**< size of the buffer */ + size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */ + lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal identifiers + * to the literal offsets + * in snapshot */ + uint32_t *out_map_len_p) /**< [out] number of literals */ +{ + if (lit_pool_p->item_count == 0) + { + *out_map_p = NULL; + *out_map_len_p = 0; + } + + uint32_t lit_table_size = 0; + size_t max_lit_table_size = buffer_size - *in_out_buffer_offset_p; + + if (max_lit_table_size > (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT)) + { + max_lit_table_size = (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT); + } + + ecma_value_t *lit_buffer_p = lit_pool_p->buffer_p; + + /* Compute the size of the literal pool. */ + for (uint32_t i = 0; i < lit_pool_p->item_count; i++) + { + if (ecma_is_value_float_number (lit_buffer_p[i])) + { + lit_table_size += (uint32_t) sizeof (ecma_number_t); + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (lit_buffer_p[i])) + { + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]); + + lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint32_t) + ECMA_BIGINT_GET_SIZE (bigint_p), + JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]); + + lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p), + JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } + + /* Check whether enough space is available and the maximum size is not reached. */ + if (lit_table_size > max_lit_table_size) + { + ecma_collection_destroy (lit_pool_p); + return false; + } + } + + lit_mem_to_snapshot_id_map_entry_t *map_p; + uint32_t total_count = lit_pool_p->item_count; + + map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t)); + + /* Set return values (no error is possible from here). */ + JERRY_ASSERT ((*in_out_buffer_offset_p % sizeof (uint32_t)) == 0); + + uint8_t *destination_p = (uint8_t *) (buffer_p + (*in_out_buffer_offset_p / sizeof (uint32_t))); + uint32_t literal_offset = 0; + + *in_out_buffer_offset_p += lit_table_size; + *out_map_p = map_p; + *out_map_len_p = total_count; + + lit_buffer_p = lit_pool_p->buffer_p; + + /* Generate literal pool data. */ + for (uint32_t i = 0; i < lit_pool_p->item_count; i++) + { + map_p->literal_id = lit_buffer_p[i]; + map_p->literal_offset = (literal_offset << JERRY_SNAPSHOT_LITERAL_SHIFT) | ECMA_TYPE_SNAPSHOT_OFFSET; + + lit_utf8_size_t length; + + if (ecma_is_value_float_number (lit_buffer_p[i])) + { + map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_NUMBER; + + ecma_number_t num = ecma_get_float_from_value (lit_buffer_p[i]); + memcpy (destination_p, &num, sizeof (ecma_number_t)); + + length = JERRY_ALIGNUP (sizeof (ecma_number_t), JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (lit_buffer_p[i])) + { + map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_BIGINT; + + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]); + uint32_t size = ECMA_BIGINT_GET_SIZE (bigint_p); + + memcpy (destination_p, &bigint_p->u.bigint_sign_and_size, sizeof (uint32_t)); + memcpy (destination_p + sizeof (uint32_t), ECMA_BIGINT_GET_DIGITS (bigint_p, 0), size); + + length = JERRY_ALIGNUP (sizeof (uint32_t) + size, JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]); + length = ecma_string_get_size (string_p); + + *(uint16_t *) destination_p = (uint16_t) length; + + ecma_string_to_cesu8_bytes (string_p, destination_p + sizeof (uint16_t), length); + + length = JERRY_ALIGNUP (sizeof (uint16_t) + length, JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } + + JERRY_ASSERT ((length % sizeof (uint16_t)) == 0); + destination_p += length; + literal_offset += length; + + map_p++; + } + + ecma_collection_destroy (lit_pool_p); + return true; +} /* ecma_save_literals_for_snapshot */ + +#endif /* JERRY_SNAPSHOT_SAVE */ + +#if JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE + +/** + * Get the compressed pointer of a given literal. + * + * @return literal compressed pointer + */ +ecma_value_t +ecma_snapshot_get_literal (const uint8_t *literal_base_p, /**< literal start */ + ecma_value_t literal_value) /**< string / number offset */ +{ + JERRY_ASSERT ((literal_value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET); + + const uint8_t *literal_p = literal_base_p + (literal_value >> JERRY_SNAPSHOT_LITERAL_SHIFT); + + if (literal_value & JERRY_SNAPSHOT_LITERAL_IS_NUMBER) + { + ecma_number_t num; + memcpy (&num, literal_p, sizeof (ecma_number_t)); + return ecma_find_or_create_literal_number (num); + } + +#if JERRY_BUILTIN_BIGINT + if (literal_value & JERRY_SNAPSHOT_LITERAL_IS_BIGINT) + { + uint32_t bigint_sign_and_size = *(uint32_t *) literal_p; + uint32_t size = bigint_sign_and_size & ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1); + + ecma_extended_primitive_t *bigint_p = ecma_bigint_create (size); + + if (bigint_p == NULL) + { + jerry_fatal (JERRY_FATAL_OUT_OF_MEMORY); + } + + /* Only the sign bit can differ. */ + JERRY_ASSERT (bigint_p->u.bigint_sign_and_size == (bigint_sign_and_size & ~(uint32_t) ECMA_BIGINT_SIGN)); + + bigint_p->u.bigint_sign_and_size = bigint_sign_and_size; + memcpy (ECMA_BIGINT_GET_DIGITS (bigint_p, 0), literal_p + sizeof (uint32_t), size); + return ecma_find_or_create_literal_bigint (ecma_make_extended_primitive_value (bigint_p, ECMA_TYPE_BIGINT)); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + uint16_t length = *(const uint16_t *) literal_p; + + return ecma_find_or_create_literal_string (literal_p + sizeof (uint16_t), length, false); +} /* ecma_snapshot_get_literal */ + +/** + * Compute the start of the serializable ecma-values of the bytecode + * Related values: + * - function argument names, if CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED is present + * - function name, if CBC_CODE_FLAGS_CLASS_CONSTRUCTOR is not present and es.next profile is enabled + * + * @return pointer to the beginning of the serializable ecma-values + */ +ecma_value_t * +ecma_snapshot_resolve_serializable_values (const ecma_compiled_code_t *compiled_code_p, /**< compiled code */ + uint8_t *bytecode_end_p) /**< end of the bytecode */ +{ + ecma_value_t *base_p = (ecma_value_t *) bytecode_end_p; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + uint32_t argument_end; + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + argument_end = ((cbc_uint16_arguments_t *) compiled_code_p)->argument_end; + } + else + { + argument_end = ((cbc_uint8_arguments_t *) compiled_code_p)->argument_end; + } + + base_p -= argument_end; + } + + /* function name */ + if (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + base_p--; + } + + return base_p; +} /* ecma_snapshot_resolve_serializable_values */ +#endif /* JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h new file mode 100644 index 00000000..6850a868 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-literal-storage.h @@ -0,0 +1,72 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LIT_STORAGE_H +#define ECMA_LIT_STORAGE_H + +#include "ecma-globals.h" + +#include "jmem.h" +#include "lit-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmalitstorage Literal storage + * @{ + */ + +#if JERRY_SNAPSHOT_SAVE +/** + * Snapshot literal - offset map + */ +typedef struct +{ + ecma_value_t literal_id; /**< literal id */ + ecma_value_t literal_offset; /**< literal offset */ +} lit_mem_to_snapshot_id_map_entry_t; +#endif /* JERRY_SNAPSHOT_SAVE */ + +void ecma_finalize_lit_storage (void); + +ecma_value_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, lit_utf8_size_t size, bool is_ascii); +ecma_value_t ecma_find_or_create_literal_number (ecma_number_t number_arg); +#if JERRY_BUILTIN_BIGINT +ecma_value_t ecma_find_or_create_literal_bigint (ecma_value_t bigint); +#endif /* JERRY_BUILTIN_BIGINT */ + +#if JERRY_SNAPSHOT_SAVE +void ecma_save_literals_append_value (ecma_value_t value, ecma_collection_t *lit_pool_p); +void ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, ecma_collection_t *lit_pool_p); +bool ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, + uint32_t *buffer_p, + size_t buffer_size, + size_t *in_out_buffer_offset_p, + lit_mem_to_snapshot_id_map_entry_t **out_map_p, + uint32_t *out_map_len_p); +#endif /* JERRY_SNAPSHOT_SAVE */ + +#if JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE +ecma_value_t ecma_snapshot_get_literal (const uint8_t *literal_base_p, ecma_value_t literal_value); +ecma_value_t *ecma_snapshot_resolve_serializable_values (const ecma_compiled_code_t *compiled_code_p, + uint8_t *byte_code_end_p); +#endif /* JERRY_SNAPSHOT_EXEC || JERRY_SNAPSHOT_SAVE */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_LIT_STORAGE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.cpp new file mode 100644 index 00000000..62ac2ae7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.cpp @@ -0,0 +1,1444 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-module.h" + +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" +#include "vm.h" + +#if JERRY_MODULE_SYSTEM + +/** + * Type of the result returned by ecma_module_resolve_export. + */ +typedef enum +{ + ECMA_MODULE_RESOLVE_NOT_FOUND, /**< reference not found */ + ECMA_MODULE_RESOLVE_CIRCULAR, /**< only circular references are found */ + ECMA_MODULE_RESOLVE_ERROR, /**< module in error state is encountered */ + ECMA_MODULE_RESOLVE_AMBIGUOUS, /**< reference is ambiguous */ + ECMA_MODULE_RESOLVE_FOUND, /**< reference found */ +} ecma_module_resolve_result_type_t; + +/** + * A record that stores the result of ecma_module_resolve_export. + */ +typedef struct +{ + ecma_module_resolve_result_type_t result_type; /**< result type */ + ecma_value_t result; /**< result value */ +} ecma_module_resolve_result_t; + +/** + * This flag is set in the result if the value is a namespace object. + */ +#define ECMA_MODULE_NAMESPACE_RESULT_FLAG 0x2 + +/** + * Initialize context variables for the root module. + * + * @return new module + */ +ecma_module_t * +ecma_module_create (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (module_current_p) == NULL); + + ecma_object_t *obj_p = ecma_create_object (NULL, sizeof (ecma_module_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_MODULE; + ext_object_p->u.cls.u1.module_state = JERRY_MODULE_STATE_UNLINKED; + ext_object_p->u.cls.u2.module_flags = 0; + + ecma_module_t *module_p = (ecma_module_t *) obj_p; + + module_p->scope_p = NULL; + module_p->namespace_object_p = NULL; + module_p->imports_p = NULL; + module_p->local_exports_p = NULL; + module_p->indirect_exports_p = NULL; + module_p->star_exports_p = NULL; + module_p->u.compiled_code_p = NULL; + + return module_p; +} /* ecma_module_create */ + +/** + * Cleanup context variables for the root module. + */ +void +ecma_module_cleanup_context (void) +{ + ecma_deref_object ((ecma_object_t *) JERRY_CONTEXT (module_current_p)); +#ifndef JERRY_NDEBUG + JERRY_CONTEXT (module_current_p) = NULL; +#endif /* JERRY_NDEBUG */ +} /* ecma_module_cleanup_context */ + +/** + * Sets module state to error. + */ +static void +ecma_module_set_error_state (ecma_module_t *module_p) /**< module */ +{ + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_ERROR; + + if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL && !jcontext_has_pending_abort ()) + { + jerry_value_t exception = jcontext_take_exception (); + + JERRY_CONTEXT (module_state_changed_callback_p) + (JERRY_MODULE_STATE_ERROR, + ecma_make_object_value (&module_p->header.object), + exception, + JERRY_CONTEXT (module_state_changed_callback_user_p)); + jcontext_raise_exception (exception); + } +} /* ecma_module_set_error_state */ + +/** + * Gets the internal module pointer of a module + * + * @return module pointer + */ +static inline ecma_module_t * +ecma_module_get_from_object (ecma_value_t module_val) /**< module */ +{ + JERRY_ASSERT (ecma_is_value_object (module_val)); + + ecma_object_t *object_p = ecma_get_object_from_value (module_val); + + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE)); + + return (ecma_module_t *) object_p; +} /* ecma_module_get_from_object */ + +/** + * Cleans up a list of module names. + */ +void +ecma_module_release_module_names (ecma_module_names_t *module_name_p) /**< first module name */ +{ + while (module_name_p != NULL) + { + ecma_module_names_t *next_p = module_name_p->next_p; + + ecma_deref_ecma_string (module_name_p->imex_name_p); + ecma_deref_ecma_string (module_name_p->local_name_p); + jmem_heap_free_block (module_name_p, sizeof (ecma_module_names_t)); + + module_name_p = next_p; + } +} /* ecma_module_release_module_names */ + +/** + * Cleans up a list of module nodes. + */ +static void +ecma_module_release_module_nodes (ecma_module_node_t *module_node_p, /**< first module node */ + bool is_import) /**< free path variable */ +{ + while (module_node_p != NULL) + { + ecma_module_node_t *next_p = module_node_p->next_p; + + ecma_module_release_module_names (module_node_p->module_names_p); + + if (is_import && ecma_is_value_string (module_node_p->u.path_or_module)) + { + ecma_deref_ecma_string (ecma_get_string_from_value (module_node_p->u.path_or_module)); + } + + jmem_heap_free_block (module_node_p, sizeof (ecma_module_node_t)); + module_node_p = next_p; + } +} /* ecma_module_release_module_nodes */ + +/** + * Creates a new resolve set item from a {module, export_name} pair. + * + * @return new resolve set item + */ +static ecma_module_resolve_set_t * +ecma_module_resolve_set_create (ecma_module_t *const module_p, /**< module */ + ecma_string_t *const export_name_p) /**< export name */ +{ + ecma_module_resolve_set_t *new_p; + new_p = (ecma_module_resolve_set_t *) jmem_heap_alloc_block (sizeof (ecma_module_resolve_set_t)); + + new_p->next_p = NULL; + new_p->module_p = module_p; + new_p->name_p = export_name_p; + + return new_p; +} /* ecma_module_resolve_set_create */ + +/** + * Appends a {module, export_name} record into a resolve set. + * + * @return true - if the record is appended successfully + * false - otherwise + */ +static bool +ecma_module_resolve_set_append (ecma_module_resolve_set_t *set_p, /**< resolve set */ + ecma_module_t *const module_p, /**< module */ + ecma_string_t *const export_name_p) /**< export name */ +{ + JERRY_ASSERT (set_p != NULL); + ecma_module_resolve_set_t *current_p = set_p; + + while (true) + { + if (current_p->module_p == module_p && ecma_compare_ecma_strings (current_p->name_p, export_name_p)) + { + return false; + } + + ecma_module_resolve_set_t *next_p = current_p->next_p; + + if (next_p == NULL) + { + current_p->next_p = ecma_module_resolve_set_create (module_p, export_name_p); + return true; + } + + current_p = next_p; + } +} /* ecma_module_resolve_set_append */ + +/** + * Cleans up contents of a resolve set. + */ +static void +ecma_module_resolve_set_cleanup (ecma_module_resolve_set_t *set_p) /**< resolve set */ +{ + while (set_p != NULL) + { + ecma_module_resolve_set_t *next_p = set_p->next_p; + jmem_heap_free_block (set_p, sizeof (ecma_module_resolve_set_t)); + set_p = next_p; + } +} /* ecma_module_resolve_set_cleanup */ + +/** + * Throws the appropriate error based on the resolve result + * + * @return error value + */ +static ecma_value_t +ecma_module_resolve_throw (ecma_module_resolve_result_t *resolve_result_p, /**< resolve result */ + ecma_string_t *name_p) /**< referenced value */ +{ +#if JERRY_ERROR_MESSAGES + ecma_value_t name_val = ecma_make_string_value (name_p); + const char *msg_p; + + switch (resolve_result_p->result_type) + { + case ECMA_MODULE_RESOLVE_CIRCULAR: + { + msg_p = "Detected cycle while resolving name '%' (module)"; + break; + } + case ECMA_MODULE_RESOLVE_AMBIGUOUS: + { + msg_p = "Name '%' is ambiguous (module)"; + break; + } + default: + { + JERRY_ASSERT (resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND + || resolve_result_p->result_type == ECMA_MODULE_RESOLVE_ERROR); + + msg_p = "Name '%' is not found (module)"; + break; + } + } + + return ecma_raise_standard_error_with_format (JERRY_ERROR_SYNTAX, msg_p, name_val); +#else /* JERRY_ERROR_MESSAGES */ + JERRY_UNUSED (resolve_result_p); + JERRY_UNUSED (name_p); + + return ecma_raise_syntax_error (ECMA_ERR_EMPTY); +#endif /* !JERRY_ERROR_MESSAGES */ +} /* ecma_module_resolve_throw */ + +/** + * Updates the resolve record with the passed type/value pair + * + * @return true - if the record is updated successfully + * false - otherwise + */ +static bool +ecma_module_resolve_update (ecma_module_resolve_result_t *resolve_result_p, /**< [in,out] resolve result */ + ecma_value_t result) /**< result value */ +{ + JERRY_ASSERT (resolve_result_p->result_type != ECMA_MODULE_RESOLVE_AMBIGUOUS + && resolve_result_p->result_type != ECMA_MODULE_RESOLVE_ERROR); + + if (resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND + || resolve_result_p->result_type == ECMA_MODULE_RESOLVE_CIRCULAR) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_FOUND; + resolve_result_p->result = result; + return true; + } + + JERRY_ASSERT (resolve_result_p->result_type == ECMA_MODULE_RESOLVE_FOUND); + + if (resolve_result_p->result == result) + { + return true; + } + + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_AMBIGUOUS; + return false; +} /* ecma_module_resolve_update */ + +/** + * Finds the reference in the imported bindings. + * + * Note: + * This function is needed because the namespace object is created before the imports are connected + * + * @return true - if the record is updated successfully + * false - otherwise + */ +static bool +ecma_module_resolve_import (ecma_module_resolve_result_t *resolve_result_p, /**< [in,out] resolve result */ + ecma_module_resolve_set_t *resolve_set_p, /**< resolve set */ + ecma_module_t *module_p, /**< base module */ + ecma_string_t *local_name_p) /**< local name */ +{ + ecma_module_node_t *import_node_p = module_p->imports_p; + + while (true) + { + JERRY_ASSERT (import_node_p != NULL); + + for (ecma_module_names_t *import_names_p = import_node_p->module_names_p; import_names_p != NULL; + import_names_p = import_names_p->next_p) + { + if (ecma_compare_ecma_strings (local_name_p, import_names_p->local_name_p)) + { + ecma_module_t *imported_module_p = ecma_module_get_from_object (import_node_p->u.path_or_module); + + if (ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p, LIT_MAGIC_STRING_ASTERIX_CHAR)) + { + /* Namespace import. */ + ecma_value_t ns = ecma_make_object_value (imported_module_p->namespace_object_p); + + JERRY_ASSERT (ns & ECMA_MODULE_NAMESPACE_RESULT_FLAG); + + return ecma_module_resolve_update (resolve_result_p, ns); + } + + if (!ecma_module_resolve_set_append (resolve_set_p, imported_module_p, import_names_p->imex_name_p) + && resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_CIRCULAR; + } + + return true; + } + } + + import_node_p = import_node_p->next_p; + } +} /* ecma_module_resolve_import */ + +/** + * Resolves which module satisfies an export based from a specific module in the import tree. + * + * Note: See ES11 15.2.1.17.3 + */ +static void +ecma_module_resolve_export (ecma_module_t *const module_p, /**< base module */ + ecma_string_t *const export_name_p, /**< export name */ + ecma_module_resolve_result_t *resolve_result_p) /**< [out] resolve result */ +{ + ecma_module_resolve_set_t *resolve_set_p = ecma_module_resolve_set_create (module_p, export_name_p); + ecma_module_resolve_set_t *current_set_p = resolve_set_p; + ecma_module_node_t *star_export_p; + + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_NOT_FOUND; + resolve_result_p->result = ECMA_VALUE_UNDEFINED; + + do + { + ecma_module_t *current_module_p = current_set_p->module_p; + ecma_string_t *current_export_name_p = current_set_p->name_p; + + if (current_module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_ERROR) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_ERROR; + goto exit; + } + + if (current_module_p->header.u.cls.u2.module_flags & ECMA_MODULE_HAS_NAMESPACE) + { + ecma_property_t *property_p = + ecma_find_named_property (current_module_p->namespace_object_p, current_export_name_p); + + if (property_p != NULL) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + JERRY_ASSERT ( + (!(*property_p & ECMA_PROPERTY_FLAG_DATA) && !(property_value_p->value & ECMA_MODULE_NAMESPACE_RESULT_FLAG)) + || ((*property_p & ECMA_PROPERTY_FLAG_DATA) && ecma_is_value_object (property_value_p->value) + && ecma_object_class_is (ecma_get_object_from_value (property_value_p->value), + ECMA_OBJECT_CLASS_MODULE_NAMESPACE))); + + if (!ecma_module_resolve_update (resolve_result_p, property_value_p->value)) + { + goto exit; + } + + goto next_iteration; + } + } + else + { + /* 6. */ + ecma_module_names_t *export_names_p = current_module_p->local_exports_p; + + while (export_names_p != NULL) + { + if (ecma_compare_ecma_strings (current_export_name_p, export_names_p->imex_name_p)) + { + ecma_property_t *property_p = + ecma_find_named_property (current_module_p->scope_p, export_names_p->local_name_p); + + if (property_p != NULL) + { + ecma_value_t reference = ecma_property_to_reference (property_p); + + JERRY_ASSERT (!(reference & ECMA_MODULE_NAMESPACE_RESULT_FLAG)); + + if (!ecma_module_resolve_update (resolve_result_p, reference)) + { + goto exit; + } + } + else if (!ecma_module_resolve_import (resolve_result_p, + resolve_set_p, + current_module_p, + export_names_p->local_name_p)) + { + goto exit; + } + + goto next_iteration; + } + + export_names_p = export_names_p->next_p; + } + + /* 7. */ + ecma_module_node_t *indirect_export_p = current_module_p->indirect_exports_p; + + while (indirect_export_p != NULL) + { + export_names_p = indirect_export_p->module_names_p; + + while (export_names_p != NULL) + { + if (ecma_compare_ecma_strings (current_export_name_p, export_names_p->imex_name_p)) + { + ecma_module_t *target_module_p = ecma_module_get_from_object (*indirect_export_p->u.module_object_p); + + if (ecma_compare_ecma_string_to_magic_id (export_names_p->local_name_p, LIT_MAGIC_STRING_ASTERIX_CHAR)) + { + /* Namespace export. */ + ecma_value_t ns = ecma_make_object_value (target_module_p->namespace_object_p); + + JERRY_ASSERT (ns & ECMA_MODULE_NAMESPACE_RESULT_FLAG); + + if (!ecma_module_resolve_update (resolve_result_p, ns)) + { + goto exit; + } + } + else if (!ecma_module_resolve_set_append (resolve_set_p, target_module_p, export_names_p->local_name_p) + && resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_CIRCULAR; + } + + goto next_iteration; + } + + export_names_p = export_names_p->next_p; + } + + indirect_export_p = indirect_export_p->next_p; + } + } + + /* 8. */ + if (ecma_compare_ecma_string_to_magic_id (current_export_name_p, LIT_MAGIC_STRING_DEFAULT)) + { + goto exit; + } + + /* 10. */ + star_export_p = current_module_p->star_exports_p; + while (star_export_p != NULL) + { + JERRY_ASSERT (star_export_p->module_names_p == NULL); + + ecma_module_t *target_module_p = ecma_module_get_from_object (*star_export_p->u.module_object_p); + + if (!ecma_module_resolve_set_append (resolve_set_p, target_module_p, current_export_name_p) + && resolve_result_p->result_type == ECMA_MODULE_RESOLVE_NOT_FOUND) + { + resolve_result_p->result_type = ECMA_MODULE_RESOLVE_CIRCULAR; + } + + star_export_p = star_export_p->next_p; + } + +next_iteration: + current_set_p = current_set_p->next_p; + } while (current_set_p != NULL); + +exit: + ecma_module_resolve_set_cleanup (resolve_set_p); +} /* ecma_module_resolve_export */ + +/** + * Evaluates an EcmaScript module. + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_module_evaluate (ecma_module_t *module_p) /**< module */ +{ + if (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_ERROR) + { + return ecma_raise_range_error (ECMA_ERR_MODULE_IS_IN_ERROR_STATE); + } + + if (module_p->header.u.cls.u1.module_state >= JERRY_MODULE_STATE_EVALUATING) + { + return ECMA_VALUE_EMPTY; + } + + JERRY_ASSERT (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKED); + JERRY_ASSERT (module_p->scope_p != NULL); + + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATING; + + ecma_value_t ret_value; + + if (module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) + { + ret_value = ECMA_VALUE_UNDEFINED; + + if (module_p->u.callback) + { + ret_value = module_p->u.callback (ecma_make_object_value (&module_p->header.object)); + + if (JERRY_UNLIKELY (ecma_is_value_exception (ret_value))) + { + ecma_throw_exception (ret_value); + ret_value = ECMA_VALUE_ERROR; + } + } + } + else + { + ret_value = vm_run_module (module_p); + } + + if (JERRY_LIKELY (!ECMA_IS_VALUE_ERROR (ret_value))) + { + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATED; + + if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL) + { + JERRY_CONTEXT (module_state_changed_callback_p) + (JERRY_MODULE_STATE_EVALUATED, + ecma_make_object_value (&module_p->header.object), + ret_value, + JERRY_CONTEXT (module_state_changed_callback_user_p)); + } + } + else + { + ecma_module_set_error_state (module_p); + } + + if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)) + { + ecma_bytecode_deref (module_p->u.compiled_code_p); + } + + module_p->u.compiled_code_p = NULL; + return ret_value; +} /* ecma_module_evaluate */ + +/** + * Resolves an export and adds it to the modules namespace object, if the export name is not yet handled. + * Note: See 15.2.1.16.2 and 15.2.1.18 + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_module_namespace_object_add_export_if_needed (ecma_collection_t *properties_p, /**< collection of properties */ + ecma_module_t *module_p, /**< module */ + ecma_string_t *export_name_p, /**< export name */ + bool allow_default) /**< allow default export */ +{ + if (!allow_default) + { + if (ecma_compare_ecma_string_to_magic_id (export_name_p, LIT_MAGIC_STRING_DEFAULT)) + { + return ECMA_VALUE_EMPTY; + } + + /* No need to check duplications before star exports are processed. */ + ecma_value_t *buffer_p = properties_p->buffer_p; + ecma_value_t *buffer_end_p = properties_p->buffer_p + properties_p->item_count; + + while (buffer_p < buffer_end_p) + { + if (ecma_compare_ecma_strings (ecma_get_string_from_value (*buffer_p), export_name_p)) + { + return ECMA_VALUE_EMPTY; + } + + buffer_p += 2; + } + } + + ecma_module_resolve_result_t resolve_result; + ecma_module_resolve_export (module_p, export_name_p, &resolve_result); + + if (resolve_result.result_type == ECMA_MODULE_RESOLVE_AMBIGUOUS) + { + return ECMA_VALUE_EMPTY; + } + + if (resolve_result.result_type != ECMA_MODULE_RESOLVE_FOUND) + { + return ecma_module_resolve_throw (&resolve_result, export_name_p); + } + + ecma_collection_push_back (properties_p, ecma_make_string_value (export_name_p)); + ecma_collection_push_back (properties_p, resolve_result.result); + return ECMA_VALUE_EMPTY; +} /* ecma_module_namespace_object_add_export_if_needed */ + +/** + * Helper routine for heapsort algorithm. + */ +static void +ecma_module_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */ + uint32_t item_count, /**< number of items */ + uint32_t item_index) /**< index of updated item */ +{ + while (true) + { + uint32_t highest_index = item_index; + uint32_t current_index = (item_index << 1) + 2; + + if (current_index >= item_count) + { + return; + } + + if (ecma_compare_ecma_strings_relational (ecma_get_string_from_value (buffer_p[highest_index]), + ecma_get_string_from_value (buffer_p[current_index]))) + { + highest_index = current_index; + } + + current_index += 2; + + if (current_index < item_count + && ecma_compare_ecma_strings_relational (ecma_get_string_from_value (buffer_p[highest_index]), + ecma_get_string_from_value (buffer_p[current_index]))) + { + highest_index = current_index; + } + + if (highest_index == item_index) + { + return; + } + + ecma_value_t tmp = buffer_p[highest_index]; + buffer_p[highest_index] = buffer_p[item_index]; + buffer_p[item_index] = tmp; + + tmp = buffer_p[highest_index + 1]; + buffer_p[highest_index + 1] = buffer_p[item_index + 1]; + buffer_p[item_index + 1] = tmp; + + item_index = highest_index; + } +} /* ecma_module_heap_sort_shift_down */ + +/** + * Creates a namespace object for a module. + * Note: See 15.2.1.18 + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */ +{ + JERRY_ASSERT (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + JERRY_ASSERT (module_p->namespace_object_p != NULL); + JERRY_ASSERT (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_HAS_NAMESPACE)); + + ecma_module_resolve_set_t *resolve_set_p; + resolve_set_p = ecma_module_resolve_set_create (module_p, ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR)); + + /* The properties collection stores name / result item pairs. Name is always + * a string, and result can be a property reference or namespace object. */ + ecma_module_resolve_set_t *current_set_p = resolve_set_p; + ecma_collection_t *properties_p = ecma_new_collection (); + ecma_value_t result = ECMA_VALUE_EMPTY; + bool allow_default = true; + + ecma_value_t *buffer_p; + uint32_t item_count; + ecma_value_t *buffer_end_p; + + do + { + ecma_module_t *current_module_p = current_set_p->module_p; + + if (current_module_p->header.u.cls.u2.module_flags & ECMA_MODULE_HAS_NAMESPACE) + { + JERRY_ASSERT (!allow_default); + + jmem_cpointer_t prop_iter_cp = current_module_p->namespace_object_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (!ECMA_PROPERTY_IS_RAW (prop_iter_p->types[i])) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (prop_iter_p->types[i], prop_pair_p->names_cp[i]); + result = ecma_module_namespace_object_add_export_if_needed (properties_p, module_p, name_p, false); + ecma_deref_ecma_string (name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } + } + else + { + ecma_module_names_t *export_names_p = current_module_p->local_exports_p; + + if (export_names_p != NULL) + { + do + { + result = ecma_module_namespace_object_add_export_if_needed (properties_p, + module_p, + export_names_p->imex_name_p, + allow_default); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + export_names_p = export_names_p->next_p; + } while (export_names_p != NULL); + } + + ecma_module_node_t *indirect_export_p = current_module_p->indirect_exports_p; + + while (indirect_export_p != NULL) + { + export_names_p = indirect_export_p->module_names_p; + + while (export_names_p != NULL) + { + result = ecma_module_namespace_object_add_export_if_needed (properties_p, + module_p, + export_names_p->imex_name_p, + allow_default); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + export_names_p = export_names_p->next_p; + } + + indirect_export_p = indirect_export_p->next_p; + } + } + + allow_default = false; + + ecma_module_node_t *star_export_p = current_module_p->star_exports_p; + + while (star_export_p != NULL) + { + JERRY_ASSERT (star_export_p->module_names_p == NULL); + + /* Circular imports are ignored */ + ecma_module_resolve_set_append (resolve_set_p, + ecma_module_get_from_object (*star_export_p->u.module_object_p), + ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR)); + + star_export_p = star_export_p->next_p; + } + + current_set_p = current_set_p->next_p; + } while (current_set_p != NULL); + + buffer_p = properties_p->buffer_p; + item_count = properties_p->item_count; + buffer_end_p = properties_p->buffer_p + item_count; + + if (item_count >= 4) + { + /* Sort items with heapsort if at least two items are stored in the buffer. */ + uint32_t end = (item_count >> 1) & ~(uint32_t) 0x1; + + do + { + end -= 2; + ecma_module_heap_sort_shift_down (buffer_p, item_count, end); + } while (end > 0); + + end = item_count - 2; + + do + { + ecma_value_t tmp = buffer_p[end]; + buffer_p[end] = buffer_p[0]; + buffer_p[0] = tmp; + + tmp = buffer_p[end + 1]; + buffer_p[end + 1] = buffer_p[1]; + buffer_p[1] = tmp; + + ecma_module_heap_sort_shift_down (buffer_p, end, 0); + end -= 2; + } while (end > 0); + } + + buffer_end_p = properties_p->buffer_p + item_count; + + while (buffer_p < buffer_end_p) + { + if (buffer_p[1] & ECMA_MODULE_NAMESPACE_RESULT_FLAG) + { + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (module_p->namespace_object_p, + ecma_get_string_from_value (buffer_p[0]), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE, + NULL); + property_value_p->value = buffer_p[1]; + } + else + { + ecma_create_named_reference_property (module_p->namespace_object_p, + ecma_get_string_from_value (buffer_p[0]), + buffer_p[1]); + } + + buffer_p += 2; + } + + module_p->header.u.cls.u2.module_flags |= ECMA_MODULE_HAS_NAMESPACE; + + ecma_module_release_module_names (module_p->local_exports_p); + module_p->local_exports_p = NULL; + + ecma_module_release_module_nodes (module_p->indirect_exports_p, false); + module_p->indirect_exports_p = NULL; + +exit: + /* Clean up. */ + ecma_module_resolve_set_cleanup (resolve_set_p); + ecma_collection_destroy (properties_p); + return result; +} /* ecma_module_create_namespace_object */ + +/** + * Connects imported values to the current module scope. + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_module_connect_imports (ecma_module_t *module_p) +{ + ecma_object_t *local_env_p = module_p->scope_p; + JERRY_ASSERT (ecma_is_lexical_environment (local_env_p)); + + ecma_module_node_t *import_node_p = module_p->imports_p; + + /* Check that the imported bindings don't exist yet. */ + while (import_node_p != NULL) + { + ecma_module_names_t *import_names_p = import_node_p->module_names_p; + + JERRY_ASSERT (local_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK); + + while (import_names_p != NULL) + { + ecma_property_t *binding_p = ecma_find_named_property (local_env_p, import_names_p->local_name_p); + + if (binding_p != NULL) + { + return ecma_raise_syntax_error (ECMA_ERR_IMPORTED_BINDING_SHADOWS_LOCAL_VARIABLE); + } + + import_names_p = import_names_p->next_p; + } + + import_node_p = import_node_p->next_p; + } + + import_node_p = module_p->imports_p; + + /* Resolve imports and create local bindings. */ + while (import_node_p != NULL) + { + ecma_module_names_t *import_names_p = import_node_p->module_names_p; + ecma_module_t *imported_module_p = ecma_module_get_from_object (import_node_p->u.path_or_module); + + while (import_names_p != NULL) + { + if (ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p, LIT_MAGIC_STRING_ASTERIX_CHAR)) + { + /* Namespace import. */ + ecma_property_value_t *value_p; + value_p = + ecma_create_named_data_property (module_p->scope_p, import_names_p->local_name_p, ECMA_PROPERTY_FIXED, NULL); + value_p->value = ecma_make_object_value (imported_module_p->namespace_object_p); + } + else + { + ecma_module_resolve_result_t resolve_result; + ecma_module_resolve_export (imported_module_p, import_names_p->imex_name_p, &resolve_result); + + if (resolve_result.result_type != ECMA_MODULE_RESOLVE_FOUND) + { + return ecma_module_resolve_throw (&resolve_result, import_names_p->imex_name_p); + } + + if (resolve_result.result & ECMA_MODULE_NAMESPACE_RESULT_FLAG) + { + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (module_p->scope_p, + import_names_p->local_name_p, + ECMA_PROPERTY_FIXED, + NULL); + property_value_p->value = resolve_result.result; + } + else + { + ecma_create_named_reference_property (module_p->scope_p, import_names_p->local_name_p, resolve_result.result); + } + } + + import_names_p = import_names_p->next_p; + } + + ecma_module_release_module_names (import_node_p->module_names_p); + import_node_p->module_names_p = NULL; + + import_node_p = import_node_p->next_p; + } + + return ECMA_VALUE_EMPTY; +} /* ecma_module_connect_imports */ + +/** + * Initialize the current module by creating the local binding for the imported variables + * and verifying indirect exports. + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_module_initialize (ecma_module_t *module_p) /**< module */ +{ + ecma_module_node_t *import_node_p = module_p->imports_p; + + while (import_node_p != NULL) + { + /* Module is evaluated even if it is used only in export-from statements. */ + ecma_value_t result = ecma_module_evaluate (ecma_module_get_from_object (import_node_p->u.path_or_module)); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_free_value (result); + + import_node_p = import_node_p->next_p; + } + + return ECMA_VALUE_EMPTY; +} /* ecma_module_initialize */ + +/** + * Gets the internal module pointer of a module + * + * @return module pointer - if module_val is a valid module, + * NULL - otherwise + */ +ecma_module_t * +ecma_module_get_resolved_module (ecma_value_t module_val) /**< module */ +{ + if (!ecma_is_value_object (module_val)) + { + return NULL; + } + + ecma_object_t *object_p = ecma_get_object_from_value (module_val); + + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE)) + { + return NULL; + } + + return (ecma_module_t *) object_p; +} /* ecma_module_get_resolved_module */ + +/** + * A module stack for depth-first search + */ +typedef struct ecma_module_stack_item_t +{ + struct ecma_module_stack_item_t *prev_p; /**< prev in the stack */ + struct ecma_module_stack_item_t *parent_p; /**< parent item in the stack */ + ecma_module_t *module_p; /**< currently processed module */ + ecma_module_node_t *node_p; /**< currently processed node */ + uint32_t dfs_index; /**< dfs index (ES2020 15.2.1.16) */ +} ecma_module_stack_item_t; + +/** + * Link module dependencies + * + * @return ECMA_VALUE_ERROR - if an error occurred + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +ecma_module_link (ecma_module_t *module_p, /**< root module */ + jerry_module_resolve_cb_t callback, /**< resolve module callback */ + void *user_p) /**< pointer passed to the resolve callback */ +{ + if (module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_UNLINKED) + { + return ecma_raise_type_error (ECMA_ERR_MODULE_MUST_BE_IN_UNLINKED_STATE); + } + + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKING; + + uint32_t dfs_index = 0; + ecma_module_stack_item_t *last_p; + ecma_module_node_t *node_p; + + last_p = (ecma_module_stack_item_t *) jmem_heap_alloc_block (sizeof (ecma_module_stack_item_t)); + last_p->prev_p = NULL; + last_p->parent_p = NULL; + last_p->module_p = module_p; + last_p->node_p = module_p->imports_p; + last_p->dfs_index = dfs_index; + + module_p->header.u.cls.u3.dfs_ancestor_index = dfs_index; + + ecma_value_t module_val = ecma_make_object_value (&module_p->header.object); + ecma_module_stack_item_t *current_p = last_p; + +restart: + /* Entering into processing new node phase. Resolve dependencies first. */ + node_p = current_p->node_p; + + JERRY_ASSERT (ecma_module_get_from_object (module_val)->imports_p == node_p); + + while (node_p != NULL) + { + ecma_module_t *resolved_module_p; + + if (!ecma_is_value_object (node_p->u.path_or_module)) + { + JERRY_ASSERT (ecma_is_value_string (node_p->u.path_or_module)); + + ecma_value_t resolve_result = callback (node_p->u.path_or_module, module_val, user_p); + + if (JERRY_UNLIKELY (ecma_is_value_exception (resolve_result))) + { + ecma_throw_exception (resolve_result); + goto error; + } + + resolved_module_p = ecma_module_get_resolved_module (resolve_result); + + if (resolved_module_p == NULL) + { + ecma_free_value (resolve_result); + ecma_raise_type_error (ECMA_ERR_CALLBACK_RESULT_NOT_MODULE); + goto error; + } + + ecma_deref_ecma_string (ecma_get_string_from_value (node_p->u.path_or_module)); + node_p->u.path_or_module = resolve_result; + ecma_deref_object (ecma_get_object_from_value (resolve_result)); + } + else + { + resolved_module_p = ecma_module_get_from_object (node_p->u.path_or_module); + } + + if (resolved_module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_ERROR) + { + ecma_raise_type_error (ECMA_ERR_LINK_TO_MODULE_IN_ERROR_STATE); + goto error; + } + + node_p = node_p->next_p; + } + + /* Find next unlinked node, or return to parent */ + while (true) + { + ecma_module_t *current_module_p = current_p->module_p; + node_p = current_p->node_p; + + while (node_p != NULL) + { + module_p = ecma_module_get_from_object (node_p->u.path_or_module); + + if (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_UNLINKED) + { + current_p->node_p = node_p->next_p; + module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKING; + + ecma_module_stack_item_t *item_p; + item_p = (ecma_module_stack_item_t *) jmem_heap_alloc_block (sizeof (ecma_module_stack_item_t)); + + dfs_index++; + + item_p->prev_p = last_p; + item_p->parent_p = current_p; + item_p->module_p = module_p; + item_p->node_p = module_p->imports_p; + item_p->dfs_index = dfs_index; + + module_p->header.u.cls.u3.dfs_ancestor_index = dfs_index; + + last_p = item_p; + current_p = item_p; + module_val = node_p->u.path_or_module; + goto restart; + } + + if (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING) + { + uint32_t dfs_ancestor_index = module_p->header.u.cls.u3.dfs_ancestor_index; + + if (dfs_ancestor_index < current_module_p->header.u.cls.u3.dfs_ancestor_index) + { + current_module_p->header.u.cls.u3.dfs_ancestor_index = dfs_ancestor_index; + } + } + + node_p = node_p->next_p; + } + + if (current_module_p->scope_p == NULL) + { + JERRY_ASSERT (!(current_module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)); + + /* Initialize scope for handling circular references. */ + ecma_value_t result = vm_init_module_scope (current_module_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_module_set_error_state (current_module_p); + goto error; + } + + JERRY_ASSERT (result == ECMA_VALUE_EMPTY); + } + + if (current_module_p->namespace_object_p == NULL) + { + ecma_object_t *namespace_object_p = + ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + namespace_object_p->type_flags_refs &= (ecma_object_descriptor_t) ~ECMA_OBJECT_FLAG_EXTENSIBLE; + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) namespace_object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_MODULE_NAMESPACE; + ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.cls.u3.value, module_p); + + current_module_p->namespace_object_p = namespace_object_p; + ecma_deref_object (namespace_object_p); + } + + if (current_module_p->header.u.cls.u3.dfs_ancestor_index != current_p->dfs_index) + { + current_p = current_p->parent_p; + JERRY_ASSERT (current_p != NULL); + + uint32_t dfs_ancestor_index = current_module_p->header.u.cls.u3.dfs_ancestor_index; + + if (dfs_ancestor_index < current_p->module_p->header.u.cls.u3.dfs_ancestor_index) + { + current_p->module_p->header.u.cls.u3.dfs_ancestor_index = dfs_ancestor_index; + } + continue; + } + + ecma_module_stack_item_t *end_p = current_p->prev_p; + current_p = current_p->parent_p; + + ecma_module_stack_item_t *iterator_p = last_p; + + do + { + JERRY_ASSERT (iterator_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + + if (ECMA_IS_VALUE_ERROR (ecma_module_create_namespace_object (iterator_p->module_p))) + { + ecma_module_set_error_state (iterator_p->module_p); + goto error; + } + + iterator_p = iterator_p->prev_p; + } while (iterator_p != end_p); + + iterator_p = last_p; + + do + { + JERRY_ASSERT (iterator_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + + if (ECMA_IS_VALUE_ERROR (ecma_module_connect_imports (iterator_p->module_p))) + { + ecma_module_set_error_state (iterator_p->module_p); + goto error; + } + + iterator_p = iterator_p->prev_p; + } while (iterator_p != end_p); + + do + { + ecma_module_stack_item_t *prev_p = last_p->prev_p; + + JERRY_ASSERT (last_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + last_p->module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKED; + + if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL) + { + JERRY_CONTEXT (module_state_changed_callback_p) + (JERRY_MODULE_STATE_LINKED, + ecma_make_object_value (&last_p->module_p->header.object), + ECMA_VALUE_UNDEFINED, + JERRY_CONTEXT (module_state_changed_callback_user_p)); + } + + jmem_heap_free_block (last_p, sizeof (ecma_module_stack_item_t)); + last_p = prev_p; + } while (last_p != end_p); + + if (current_p == NULL) + { + return ECMA_VALUE_TRUE; + } + } + +error: + JERRY_ASSERT (last_p != NULL); + + do + { + ecma_module_stack_item_t *prev_p = last_p->prev_p; + + if (last_p->module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_ERROR) + { + JERRY_ASSERT (last_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING); + last_p->module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_UNLINKED; + } + + jmem_heap_free_block (last_p, sizeof (ecma_module_stack_item_t)); + last_p = prev_p; + } while (last_p != NULL); + + return ECMA_VALUE_ERROR; +} /* ecma_module_link */ + +/** + * Compute the result of 'import()' calls + * + * @return promise object representing the result of the operation + */ +ecma_value_t +ecma_module_import (ecma_value_t specifier, /**< module specifier */ + ecma_value_t user_value) /**< user value assigned to the script */ +{ + ecma_string_t *specifier_p = ecma_op_to_string (specifier); + ecma_module_t *module_p; + + if (JERRY_UNLIKELY (specifier_p == NULL)) + { + goto error; + } + + if (JERRY_CONTEXT (module_import_callback_p) == NULL) + { + ecma_deref_ecma_string (specifier_p); + goto error_module_instantiate; + } + + jerry_value_t result; + result = JERRY_CONTEXT (module_import_callback_p) (ecma_make_string_value (specifier_p), + user_value, + JERRY_CONTEXT (module_import_callback_user_p)); + ecma_deref_ecma_string (specifier_p); + + if (JERRY_UNLIKELY (ecma_is_value_exception (result))) + { + ecma_throw_exception (result); + goto error; + } + + if (ecma_is_value_object (result) && ecma_is_promise (ecma_get_object_from_value (result))) + { + return result; + } + + module_p = ecma_module_get_resolved_module (result); + + if (module_p == NULL) + { + ecma_free_value (result); + goto error_module_instantiate; + } + + if (module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_EVALUATED) + { + ecma_deref_object (&module_p->header.object); + goto error_module_instantiate; + } + + result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + ecma_fulfill_promise (result, ecma_make_object_value (module_p->namespace_object_p)); + ecma_deref_object (&module_p->header.object); + return result; + +error_module_instantiate: + ecma_raise_range_error (ECMA_ERR_MODULE_CANNOT_BE_INSTANTIATED); + +error: + if (jcontext_has_pending_abort ()) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t exception = jcontext_take_exception (); + + ecma_value_t promise = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + ecma_reject_promise (promise, exception); + ecma_free_value (exception); + return promise; +} /* ecma_module_import */ + +/** + * Cleans up and releases a module structure including all referenced modules. + */ +void +ecma_module_release_module (ecma_module_t *module_p) /**< module */ +{ + jerry_module_state_t state = (jerry_module_state_t) module_p->header.u.cls.u1.module_state; + + JERRY_ASSERT (state != JERRY_MODULE_STATE_INVALID); + +#ifndef JERRY_NDEBUG + module_p->scope_p = NULL; + module_p->namespace_object_p = NULL; +#endif /* JERRY_NDEBUG */ + + ecma_module_release_module_names (module_p->local_exports_p); + + if (module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) + { + return; + } + + ecma_module_release_module_nodes (module_p->imports_p, true); + ecma_module_release_module_nodes (module_p->indirect_exports_p, false); + ecma_module_release_module_nodes (module_p->star_exports_p, false); + + if (module_p->u.compiled_code_p != NULL) + { + ecma_bytecode_deref (module_p->u.compiled_code_p); +#ifndef JERRY_NDEBUG + module_p->u.compiled_code_p = NULL; +#endif /* JERRY_NDEBUG */ + } +} /* ecma_module_release_module */ + +#endif /* JERRY_MODULE_SYSTEM */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.h new file mode 100644 index 00000000..ceb47ec6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-module.h @@ -0,0 +1,132 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_MODULE_H +#define ECMA_MODULE_H + +#include "ecma-globals.h" + +#include "common.h" + +#if JERRY_MODULE_SYSTEM + +#define ECMA_MODULE_MAX_PATH 255u + +/** + * Module status flags. + */ +typedef enum +{ + ECMA_MODULE_IS_NATIVE = (1 << 0), /**< native module */ + ECMA_MODULE_HAS_NAMESPACE = (1 << 1), /**< namespace object has been initialized */ +} ecma_module_flags_t; + +/** + * Imported or exported names, such as "a as b" + * Note: See https://www.ecma-international.org/ecma-262/6.0/#table-39 + * and https://www.ecma-international.org/ecma-262/6.0/#table-41 + */ +typedef struct ecma_module_names +{ + struct ecma_module_names *next_p; /**< next linked list node */ + ecma_string_t *imex_name_p; /**< Import/export name of the item */ + ecma_string_t *local_name_p; /**< Local name of the item */ +} ecma_module_names_t; + +/** + * Module structure storing an instance of a module + * + * Note: + * The imports_p list follows the order of import-from/export-from statements in the source + * code of a module, even if a given module specifier is only used by export-from statements. + */ +typedef struct ecma_module +{ + /* Note: state is stored in header.u.class_prop.extra_info */ + ecma_extended_object_t header; /**< header part */ + /* TODO(dbatyai): These could be compressed pointers */ + ecma_object_t *scope_p; /**< lexical lenvironment of the module */ + ecma_object_t *namespace_object_p; /**< namespace object of the module */ + struct ecma_module_node *imports_p; /**< import requests of the module */ + ecma_module_names_t *local_exports_p; /**< local exports of the module */ + struct ecma_module_node *indirect_exports_p; /**< indirect exports of the module */ + struct ecma_module_node *star_exports_p; /**< star exports of the module */ + + /* Code used for evaluating a module */ + union + { + ecma_compiled_code_t *compiled_code_p; /**< compiled code for the module */ + jerry_native_module_evaluate_cb_t callback; /**< callback for evaluating native modules */ + } u; +} ecma_module_t; + +/** + * Module node to store imports / exports. + * + * Note: + * Only one module node is created for each module specifier: the names are + * concatenated if the same specifier is used multiple times in the source code. + * However, multiple nodes are created for modules with multiple alias + * (for example ./a.mjs and ././a.mjs can refer to the same module). + */ +typedef struct ecma_module_node +{ + struct ecma_module_node *next_p; /**< next linked list node */ + ecma_module_names_t *module_names_p; /**< names of the requested import/export node */ + + union + { + ecma_value_t path_or_module; /**< imports: module specifier (if string) or module reference (if object) */ + ecma_value_t *module_object_p; /**< non-imports: reference to a path_or_module field in the imports */ + } u; +} ecma_module_node_t; + +/** + * A list of module records that can be used to identify circular imports during resolution + */ +typedef struct ecma_module_resolve_set +{ + struct ecma_module_resolve_set *next_p; /**< next in linked list */ + ecma_module_t *module_p; /**< module */ + ecma_string_t *name_p; /**< identifier name */ +} ecma_module_resolve_set_t; + +/** + * A list that is used like a stack to drive the resolution process, instead of recursion. + */ +typedef struct ecma_module_resolve_stack +{ + struct ecma_module_resolve_stack *next_p; /**< next in linked list */ + ecma_module_t *module_p; /**< module request */ + ecma_string_t *export_name_p; /**< export identifier name */ + bool resolving; /**< flag storing wether the current frame started resolving */ +} ecma_module_resolve_stack_t; + +ecma_value_t ecma_module_initialize (ecma_module_t *module_p); +ecma_module_t *ecma_module_get_resolved_module (ecma_value_t module_val); + +ecma_value_t ecma_module_link (ecma_module_t *module_p, jerry_module_resolve_cb_t callback_p, void *user_p); +ecma_value_t ecma_module_evaluate (ecma_module_t *module_p); +ecma_value_t ecma_module_import (ecma_value_t specifier, ecma_value_t user_value); + +ecma_module_t *ecma_module_create (void); +void ecma_module_cleanup_context (void); + +void ecma_module_release_module_names (ecma_module_names_t *module_name_p); +void ecma_module_release_module (ecma_module_t *module_p); + +#endif /* JERRY_MODULE_SYSTEM */ + +#endif /* !ECMA_MODULE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.cpp new file mode 100644 index 00000000..370b1fc7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.cpp @@ -0,0 +1,532 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-property-hashmap.h" + +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmapropertyhashmap Property hashmap + * @{ + */ + +#if JERRY_PROPERTY_HASHMAP + +/** + * Compute the total size of the property hashmap. + */ +#define ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE(max_property_count) \ + (sizeof (ecma_property_hashmap_t) + (max_property_count * sizeof (jmem_cpointer_t)) + (max_property_count >> 3)) + +/** + * Number of items in the stepping table. + */ +#define ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS 8 + +/** + * Stepping values for searching items in the hashmap. + */ +static const uint8_t ecma_property_hashmap_steps[ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS] JERRY_ATTR_CONST_DATA = { + 3, 5, 7, 11, 13, 17, 19, 23 +}; + +/** + * Get the value of a bit in a bitmap. + */ +#define ECMA_PROPERTY_HASHMAP_GET_BIT(byte_p, index) ((byte_p)[(index) >> 3] & (1 << ((index) &0x7))) + +/** + * Clear the value of a bit in a bitmap. + */ +#define ECMA_PROPERTY_HASHMAP_CLEAR_BIT(byte_p, index) \ + ((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] & ~(1 << ((index) &0x7)))) + +/** + * Set the value of a bit in a bitmap. + */ +#define ECMA_PROPERTY_HASHMAP_SET_BIT(byte_p, index) \ + ((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] | (1 << ((index) &0x7)))) + +/** + * Create a new property hashmap for the object. + * The object must not have a property hashmap. + */ +void +ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ +{ + if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) != ECMA_PROP_HASHMAP_ALLOC_ON) + { + return; + } + + jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; + + if (prop_iter_cp == JMEM_CP_NULL) + { + return; + } + + uint32_t named_property_count = 0; + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])); + named_property_count++; + } + } + prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (named_property_count < (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 2)) + { + return; + } + + /* The max_property_count must be power of 2. */ + uint32_t max_property_count = ECMA_PROPERTY_HASMAP_MINIMUM_SIZE; + + /* At least 1/3 items must be NULL. */ + while (max_property_count < (named_property_count + (named_property_count >> 1))) + { + max_property_count <<= 1; + } + + size_t total_size = ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (max_property_count); + + ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block_null_on_error (total_size); + + if (hashmap_p == NULL) + { + return; + } + + memset (hashmap_p, 0, total_size); + + hashmap_p->header.types[0] = ECMA_PROPERTY_TYPE_HASHMAP; + hashmap_p->header.next_property_cp = object_p->u1.property_list_cp; + hashmap_p->max_property_count = max_property_count; + hashmap_p->null_count = max_property_count - named_property_count; + hashmap_p->unused_count = max_property_count - named_property_count; + + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + uint8_t *bits_p = (uint8_t *) (pair_list_p + max_property_count); + uint32_t mask = max_property_count - 1; + + prop_iter_cp = object_p->u1.property_list_cp; + ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, hashmap_p); + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_iter_p->types[i] == ECMA_PROPERTY_TYPE_DELETED) + { + continue; + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])); + + ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; + + uint32_t entry_index = ecma_string_get_property_name_hash (prop_iter_p->types[i], property_pair_p->names_cp[i]); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + + entry_index &= mask; +#ifndef JERRY_NDEBUG + /* Because max_property_count (power of 2) and step (a prime + * number) are relative primes, all entries of the hasmap are + * visited exactly once before the start entry index is reached + * again. Furthermore because at least one NULL is present in + * the hashmap, the while loop must be terminated before the + * the starting index is reached again. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + while (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } + + ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p); + + if (i != 0) + { + ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index); + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +} /* ecma_property_hashmap_create */ + +/** + * Free the hashmap of the object. + * The object must have a property hashmap. + */ +void +ecma_property_hashmap_free (ecma_object_t *object_p) /**< object */ +{ + /* Property hash must be exists and must be the first property. */ + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + ecma_property_header_t *property_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, object_p->u1.property_list_cp); + + JERRY_ASSERT (property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP); + + ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) property_p; + + object_p->u1.property_list_cp = property_p->next_property_cp; + + jmem_heap_free_block (hashmap_p, ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (hashmap_p->max_property_count)); +} /* ecma_property_hashmap_free */ + +/** + * Insert named property into the hashmap. + */ +void +ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */ + ecma_string_t *name_p, /**< name of the property */ + ecma_property_pair_t *property_pair_p, /**< property pair */ + int property_index) /**< property index in the pair (0 or 1) */ +{ + JERRY_ASSERT (property_pair_p != NULL); + + ecma_property_hashmap_t *hashmap_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, object_p->u1.property_list_cp); + + JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP); + + /* The NULLs are reduced below 1/8 of the hashmap. */ + if (hashmap_p->null_count < (hashmap_p->max_property_count >> 3)) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + return; + } + + JERRY_ASSERT (property_index < ECMA_PROPERTY_PAIR_ITEM_COUNT); + + uint32_t entry_index = ecma_string_hash (name_p); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + uint32_t mask = hashmap_p->max_property_count - 1; + entry_index &= mask; + +#ifndef JERRY_NDEBUG + /* See the comment for this variable in ecma_property_hashmap_create. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + + while (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } + + ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p); + + uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); + bits_p += (entry_index >> 3); + mask = (uint32_t) (1 << (entry_index & 0x7)); + + if (!(*bits_p & mask)) + { + /* Deleted entries also has ECMA_NULL_POINTER + * value, but they are not NULL values. */ + hashmap_p->null_count--; + JERRY_ASSERT (hashmap_p->null_count > 0); + } + + hashmap_p->unused_count--; + JERRY_ASSERT (hashmap_p->unused_count > 0); + + if (property_index == 0) + { + *bits_p = (uint8_t) ((*bits_p) & ~mask); + } + else + { + *bits_p = (uint8_t) ((*bits_p) | mask); + } +} /* ecma_property_hashmap_insert */ + +/** + * Delete named property from the hashmap. + * + * @return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP if hashmap should be recreated + * ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP otherwise + */ +ecma_property_hashmap_delete_status +ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ + jmem_cpointer_t name_cp, /**< property name */ + ecma_property_t *property_p) /**< property */ +{ + ecma_property_hashmap_t *hashmap_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, object_p->u1.property_list_cp); + + JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP); + + hashmap_p->unused_count++; + + /* The NULLs are above 3/4 of the hashmap. */ + if (hashmap_p->unused_count > ((hashmap_p->max_property_count * 3) >> 2)) + { + return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP; + } + + uint32_t entry_index = ecma_string_get_property_name_hash (*property_p, name_cp); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + uint32_t mask = hashmap_p->max_property_count - 1; + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); + + entry_index &= mask; + +#ifndef JERRY_NDEBUG + /* See the comment for this variable in ecma_property_hashmap_create. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + while (true) + { + if (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + size_t offset = 0; + + if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { + offset = 1; + } + + ecma_property_pair_t *property_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, pair_list_p[entry_index]); + + if ((property_pair_p->header.types + offset) == property_p) + { + JERRY_ASSERT (property_pair_p->names_cp[offset] == name_cp); + + pair_list_p[entry_index] = ECMA_NULL_POINTER; + ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index); + return ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; + } + } + else + { + /* Must be a deleted entry. */ + JERRY_ASSERT (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)); + } + + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } +} /* ecma_property_hashmap_delete */ + +/** + * Find a named property. + * + * @return pointer to the property if found or NULL otherwise + */ +ecma_property_t * +ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ + ecma_string_t *name_p, /**< property name */ + jmem_cpointer_t *property_real_name_cp) /**< [out] property real name */ +{ +#ifndef JERRY_NDEBUG + /* A sanity check in debug mode: a named property must be present + * in both the property hashmap and in the property chain, or missing + * from both data collection. The following code checks the property + * chain, and sets the property_found variable. */ + bool property_found = false; + + jmem_cpointer_t prop_iter_cp = hashmap_p->header.next_property_cp; + + while (prop_iter_cp != JMEM_CP_NULL && !property_found) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])) + { + if (ecma_string_compare_to_property_name (prop_iter_p->types[i], prop_pair_p->names_cp[i], name_p)) + { + /* Property is found */ + property_found = true; + break; + } + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +#endif /* !JERRY_NDEBUG */ + + uint32_t entry_index = ecma_string_hash (name_p); + uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; + uint32_t mask = hashmap_p->max_property_count - 1; + jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); + uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count); + entry_index &= mask; + +#ifndef JERRY_NDEBUG + /* See the comment for this variable in ecma_property_hashmap_create. */ + uint32_t start_entry_index = entry_index; +#endif /* !JERRY_NDEBUG */ + + if (ECMA_IS_DIRECT_STRING (name_p)) + { + ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p); + jmem_cpointer_t property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p); + + JERRY_ASSERT (prop_name_type > 0); + + while (true) + { + if (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + size_t offset = 0; + if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { + offset = 1; + } + + ecma_property_pair_t *property_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, pair_list_p[entry_index]); + + ecma_property_t *property_p = property_pair_p->header.types + offset; + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + if (property_pair_p->names_cp[offset] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == prop_name_type) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (property_found); +#endif /* !JERRY_NDEBUG */ + + *property_real_name_cp = property_name_cp; + return property_p; + } + } + else + { + if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (!property_found); +#endif /* !JERRY_NDEBUG */ + + return NULL; + } + /* Otherwise it is a deleted entry. */ + } + + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } + } + + while (true) + { + if (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + size_t offset = 0; + if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { + offset = 1; + } + + ecma_property_pair_t *property_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, pair_list_p[entry_index]); + + ecma_property_t *property_p = property_pair_p->header.types + offset; + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR) + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_pair_p->names_cp[offset]); + + if (ecma_compare_ecma_non_direct_strings (prop_name_p, name_p)) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (property_found); +#endif /* !JERRY_NDEBUG */ + + *property_real_name_cp = property_pair_p->names_cp[offset]; + return property_p; + } + } + } + else + { + if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (!property_found); +#endif /* !JERRY_NDEBUG */ + + return NULL; + } + /* Otherwise it is a deleted entry. */ + } + + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } +} /* ecma_property_hashmap_find */ +#endif /* JERRY_PROPERTY_HASHMAP */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h new file mode 100644 index 00000000..265075e9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.h @@ -0,0 +1,89 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_PROPERTY_HASHMAP_H +#define ECMA_PROPERTY_HASHMAP_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmapropertyhashmap Property hashmap + * @{ + */ + +/** + * Recommended minimum number of items in a property cache. + */ +#define ECMA_PROPERTY_HASMAP_MINIMUM_SIZE 32 + +/** + * Property hash. + */ +typedef struct +{ + ecma_property_header_t header; /**< header of the property */ + uint32_t max_property_count; /**< maximum property count (power of 2) */ + uint32_t null_count; /**< number of NULLs in the map */ + uint32_t unused_count; /**< number of unused entries in the map */ + + /* + * The hash is followed by max_property_count ecma_cpointer_t + * compressed pointers and (max_property_count + 7) / 8 bytes + * which stores a flag for each compressed pointer. + * + * If the compressed pointer is equal to ECMA_NULL_POINTER + * - flag is cleared if the entry is NULL + * - flag is set if the entry is deleted + * + * If the compressed pointer is not equal to ECMA_NULL_POINTER + * - flag is cleared if the first entry of a property pair is referenced + * - flag is set if the second entry of a property pair is referenced + */ +} ecma_property_hashmap_t; + +#if JERRY_PROPERTY_HASHMAP + +/** + * Simple ecma values + */ +typedef enum +{ + ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP, /**< object has no hashmap */ + ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP, /**< object has hashmap */ + ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP, /**< hashmap should be recreated */ +} ecma_property_hashmap_delete_status; + +void ecma_property_hashmap_create (ecma_object_t *object_p); +void ecma_property_hashmap_free (ecma_object_t *object_p); +void ecma_property_hashmap_insert (ecma_object_t *object_p, + ecma_string_t *name_p, + ecma_property_pair_t *property_pair_p, + int property_index); +ecma_property_hashmap_delete_status +ecma_property_hashmap_delete (ecma_object_t *object_p, jmem_cpointer_t name_cp, ecma_property_t *property_p); + +ecma_property_t *ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, + ecma_string_t *name_p, + jmem_cpointer_t *property_real_name_cp); +#endif /* JERRY_PROPERTY_HASHMAP */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_PROPERTY_HASHMAP_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/base/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/meson.build new file mode 100644 index 00000000..357e887c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/base/meson.build @@ -0,0 +1,39 @@ +source_file = [ + 'ecma-alloc.h', + 'ecma-error-messages.inc.h', + 'ecma-errors.h', + 'ecma-extended-info.h', + 'ecma-gc.h', + 'ecma-globals.h', + 'ecma-helpers-number.h', + 'ecma-helpers.h', + 'ecma-init-finalize.h', + 'ecma-lcache.h', + 'ecma-line-info.h', + 'ecma-literal-storage.h', + 'ecma-module.h', + 'ecma-property-hashmap.h', + 'ecma-alloc.cpp', + 'ecma-errors.cpp', + 'ecma-extended-info.cpp', + 'ecma-gc.cpp', + 'ecma-helpers-collection.cpp', + 'ecma-helpers-conversion.cpp', + 'ecma-helpers-errol.cpp', + 'ecma-helpers-external-pointers.cpp', + 'ecma-helpers-number.cpp', + 'ecma-helpers-string.cpp', + 'ecma-helpers-value.cpp', + 'ecma-helpers.cpp', + 'ecma-init-finalize.cpp', + 'ecma-lcache.cpp', + 'ecma-line-info.cpp', + 'ecma-literal-storage.cpp', + 'ecma-module.cpp', + 'ecma-property-hashmap.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.cpp new file mode 100644 index 00000000..771fca8e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.cpp @@ -0,0 +1,33 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-aggregateerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID aggregate_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.inc.h new file mode 100644 index 00000000..b5b3a11a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror-prototype.inc.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * AggregateError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_AGGREGATE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.cpp new file mode 100644 index 00000000..4313168b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.cpp @@ -0,0 +1,109 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-aggregateerror.inc.h" +#define BUILTIN_UNDERSCORED_ID aggregate_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup aggregateerror ECMA AggregateError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in AggregateError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_aggregate_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + ecma_value_t message_val = ECMA_VALUE_UNDEFINED; + ecma_value_t error_val = ECMA_VALUE_UNDEFINED; + + if (arguments_list_len > 0) + { + error_val = arguments_list_p[0]; + + if (arguments_list_len > 1) + { + message_val = arguments_list_p[1]; + } + } + + return ecma_new_aggregate_error (error_val, message_val); +} /* ecma_builtin_aggregate_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in AggregateError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_aggregate_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_aggregate_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_aggregate_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.inc.h new file mode 100644 index 00000000..c7f0f6fb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-aggregateerror.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * AggregateError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 2, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.cpp new file mode 100644 index 00000000..c295f7a0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.cpp @@ -0,0 +1,224 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" +#include "ecma-typedarray-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ARRAY_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_ARRAY_ITERATOR_PROTOTYPE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID array_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %arrayiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in + * @{ + */ + +/** + * The %ArrayIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 22.1.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + /* 1 - 2. */ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + /* 3. */ + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARRAY_ITERATOR)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + /* 4 - 5 */ + if (ecma_is_value_empty (iterated_value)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + ecma_object_t *array_object_p = ecma_get_object_from_value (iterated_value); + + /* 8. */ + ecma_length_t length; + if (ecma_object_is_typedarray (array_object_p)) + { + /* a. */ + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_object_p); + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* b. */ + length = ecma_typedarray_get_length (array_object_p); + } + else + { + ecma_value_t len_value = ecma_op_object_get_length (array_object_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + return len_value; + } + } + + ecma_length_t index = ext_obj_p->u.cls.u2.iterator_index; + + if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT)) + { + /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] + property is stored as an internal property */ + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_value_t index_value = ecma_op_object_get (obj_p, prop_name_p); + + if (!ecma_is_value_undefined (index_value)) + { + index = (ecma_length_t) (ecma_get_number_from_value (index_value) + 1); + } + + ecma_value_t put_result = ecma_op_object_put (obj_p, prop_name_p, ecma_make_length_value (index), true); + + JERRY_ASSERT (ecma_is_value_true (put_result)); + + ecma_free_value (index_value); + } + else + { + /* 11. */ + ext_obj_p->u.cls.u2.iterator_index++; + } + + if (index >= length) + { + ext_obj_p->u.cls.u3.iterated_value = ECMA_VALUE_EMPTY; + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + /* 7. */ + uint8_t iterator_kind = ext_obj_p->u.cls.u1.iterator_kind; + + if (iterator_kind == ECMA_ITERATOR_KEYS) + { + /* 12. */ + return ecma_create_iter_result_object (ecma_make_length_value (index), ECMA_VALUE_FALSE); + } + + /* 14. */ + ecma_value_t get_value = ecma_op_object_get_by_index (array_object_p, index); + + /* 15. */ + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + ecma_value_t result; + + /* 16. */ + if (iterator_kind == ECMA_ITERATOR_VALUES) + { + result = ecma_create_iter_result_object (get_value, ECMA_VALUE_FALSE); + } + else + { + /* 17.a */ + JERRY_ASSERT (iterator_kind == ECMA_ITERATOR_ENTRIES); + + /* 17.b */ + ecma_value_t entry_array_value; + entry_array_value = ecma_create_array_from_iter_element (get_value, ecma_make_length_value (index)); + + result = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE); + ecma_free_value (entry_array_value); + } + + ecma_free_value (get_value); + + return result; +} /* ecma_builtin_array_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_array_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_ARRAY_ITERATOR_PROTOTYPE_OBJECT_NEXT: + { + return ecma_builtin_array_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_array_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h new file mode 100644 index 00000000..c74d68da --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %ArrayIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ARRAY_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_ARRAY_ITERATOR_PROTOTYPE_OBJECT_NEXT, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.cpp new file mode 100644 index 00000000..5f67573a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.cpp @@ -0,0 +1,24 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype-unscopables.inc.h" +#define BUILTIN_UNDERSCORED_ID array_prototype_unscopables +#include "ecma-builtin-internal-routines-template.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h new file mode 100644 index 00000000..2cc4bc50 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Array.prototype[@@unscopables] built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +SIMPLE_VALUE (LIT_MAGIC_STRING_AT, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_ENTRIES, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FILL, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FIND, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FLAT, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FLATMAP, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_INCLUDES, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_KEYS, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_VALUES, ECMA_VALUE_TRUE, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp new file mode 100644 index 00000000..e6243185 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp @@ -0,0 +1,2973 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jcontext.h" +#include "jrt.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_ARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ARRAY_PROTOTYPE_ROUTINE_START = 0, + /* Note: these 2 routine ids must be in this order */ + ECMA_ARRAY_PROTOTYPE_SORT, + ECMA_ARRAY_PROTOTYPE_CONCAT, + ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING, + ECMA_ARRAY_PROTOTYPE_JOIN, + ECMA_ARRAY_PROTOTYPE_POP, + ECMA_ARRAY_PROTOTYPE_PUSH, + ECMA_ARRAY_PROTOTYPE_REVERSE, + ECMA_ARRAY_PROTOTYPE_SHIFT, + ECMA_ARRAY_PROTOTYPE_SLICE, + ECMA_ARRAY_PROTOTYPE_SPLICE, + ECMA_ARRAY_PROTOTYPE_UNSHIFT, + ECMA_ARRAY_PROTOTYPE_AT, + ECMA_ARRAY_PROTOTYPE_INDEX_OF, + ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF, + /* Note these 3 routines must be in this order */ + ECMA_ARRAY_PROTOTYPE_EVERY, + ECMA_ARRAY_PROTOTYPE_SOME, + ECMA_ARRAY_PROTOTYPE_FOR_EACH, + ECMA_ARRAY_PROTOTYPE_MAP, + ECMA_ARRAY_PROTOTYPE_FILTER, + /* Note these 2 routines must be in this order */ + ECMA_ARRAY_PROTOTYPE_REDUCE, + ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, + ECMA_ARRAY_PROTOTYPE_FIND, + ECMA_ARRAY_PROTOTYPE_FIND_INDEX, + ECMA_ARRAY_PROTOTYPE_ENTRIES, + ECMA_ARRAY_PROTOTYPE_KEYS, + ECMA_ARRAY_PROTOTYPE_SYMBOL_ITERATOR, + ECMA_ARRAY_PROTOTYPE_FILL, + ECMA_ARRAY_PROTOTYPE_COPY_WITHIN, + ECMA_ARRAY_PROTOTYPE_INCLUDES, + ECMA_ARRAY_PROTOTYPE_FLAT, + ECMA_ARRAY_PROTOTYPE_FLATMAP, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup arrayprototype ECMA Array.prototype object built-in + * @{ + */ + +/** + * Helper function to set an object's length property + * + * @return ecma value (return value of the [[Put]] method) + * Calling ecma_free_value on the returned value is optional if it is not abrupt completion. + */ +static ecma_value_t +ecma_builtin_array_prototype_helper_set_length (ecma_object_t *object, /**< object*/ + ecma_number_t length) /**< new length */ +{ + ecma_value_t length_value = ecma_make_number_value (length); + ecma_value_t ret_value = + ecma_op_object_put (object, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), length_value, true); + + ecma_free_value (length_value); + + JERRY_ASSERT (ecma_is_value_boolean (ret_value) || ecma_is_value_empty (ret_value) + || ECMA_IS_VALUE_ERROR (ret_value)); + return ret_value; +} /* ecma_builtin_array_prototype_helper_set_length */ + +/** + * The Array.prototype object's 'toLocaleString' routine + * + * See also: + * ECMA-262 v5, 15.4.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_to_locale_string (ecma_object_t *obj_p, /**< object */ + ecma_length_t length) /**< object's length */ +{ + /* 5. */ + if (length == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + /* 7-8. */ + ecma_string_t *first_string_p = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0); + + if (JERRY_UNLIKELY (first_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (first_string_p); + ecma_deref_ecma_string (first_string_p); + + /* 9-10. */ + for (ecma_length_t k = 1; k < length; k++) + { + /* 4. Implementation-defined: set the separator to a single comma character. */ + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COMMA); + + ecma_string_t *next_string_p = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k); + + if (JERRY_UNLIKELY (next_string_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_append (&builder, next_string_p); + ecma_deref_ecma_string (next_string_p); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_array_prototype_object_to_locale_string */ + +/** + * The Array.prototype object's 'concat' routine + * + * See also: + * ECMA-262 v5, 15.4.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_concat (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p) /**< array object */ +{ + /* 2. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_length_t new_length = 0; + + /* 5.b - 5.c for this_arg */ + ecma_value_t concat_this_value = + ecma_builtin_helper_array_concat_value (new_array_p, &new_length, ecma_make_object_value (obj_p)); + if (ECMA_IS_VALUE_ERROR (concat_this_value)) + { + ecma_deref_object (new_array_p); + return concat_this_value; + } + + JERRY_ASSERT (ecma_is_value_empty (concat_this_value)); + + /* 5. */ + for (uint32_t arg_index = 0; arg_index < args_number; arg_index++) + { + ecma_value_t concat_value = ecma_builtin_helper_array_concat_value (new_array_p, &new_length, args[arg_index]); + + if (ECMA_IS_VALUE_ERROR (concat_value)) + { + ecma_deref_object (new_array_p); + return concat_value; + } + + JERRY_ASSERT (ecma_is_value_empty (concat_value)); + } + + ecma_value_t set_length_value = + ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) new_length)); + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_deref_object (new_array_p); + return set_length_value; + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_concat */ + +/** + * The Array.prototype.toString's separator creation routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 4th step + * + * @return NULL - if the conversion fails + * ecma_string_t * - otherwise + */ + +static ecma_string_t * +ecma_op_array_get_separator_string (ecma_value_t separator) /**< possible separator */ +{ + if (ecma_is_value_undefined (separator)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); + } + + return ecma_op_to_string (separator); +} /* ecma_op_array_get_separator_string */ + +/** + * The Array.prototype's 'toString' single element operation routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 + * + * @return NULL - if the conversion fails + * ecma_string_t * - otherwise + */ +static ecma_string_t * +ecma_op_array_get_to_string_at_index (ecma_object_t *obj_p, /**< this object */ + ecma_length_t index) /**< array index */ +{ + ecma_value_t index_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *ret_str_p = ecma_op_to_string (index_value); + + ecma_free_value (index_value); + + return ret_str_p; +} /* ecma_op_array_get_to_string_at_index */ + +/** + * The Array.prototype object's 'join' routine + * + * See also: + * ECMA-262 v5, 15.4.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_join (ecma_value_t separator_arg, /**< separator argument */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t length) /**< object's length */ +{ + /* 4-5. */ + ecma_string_t *separator_string_p = ecma_op_array_get_separator_string (separator_arg); + + if (JERRY_UNLIKELY (separator_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + if (length == 0) + { + /* 6. */ + ecma_deref_ecma_string (separator_string_p); + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + /* 7-8. */ + ecma_string_t *first_string_p = ecma_op_array_get_to_string_at_index (obj_p, 0); + + if (JERRY_UNLIKELY (first_string_p == NULL)) + { + ecma_deref_ecma_string (separator_string_p); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (first_string_p); + ecma_deref_ecma_string (first_string_p); + + /* 9-10. */ + for (ecma_length_t k = 1; k < length; k++) + { + /* 10.a */ + ecma_stringbuilder_append (&builder, separator_string_p); + + /* 10.d */ + ecma_string_t *next_string_p = ecma_op_array_get_to_string_at_index (obj_p, k); + + if (JERRY_UNLIKELY (next_string_p == NULL)) + { + ecma_deref_ecma_string (separator_string_p); + ecma_stringbuilder_destroy (&builder); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_append (&builder, next_string_p); + ecma_deref_ecma_string (next_string_p); + } + + ecma_deref_ecma_string (separator_string_p); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_array_prototype_join */ + +/** + * The Array.prototype object's 'pop' routine + * + * See also: + * ECMA-262 v5, 15.4.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_pop (ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + /* 4.a */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO); + + /* 4.b */ + return ECMA_IS_VALUE_ERROR (set_length_value) ? set_length_value : ECMA_VALUE_UNDEFINED; + } + + /* 5.b */ + len--; + ecma_value_t get_value = ecma_op_object_get_by_index (obj_p, len); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_delete_fast_array_properties (obj_p, (uint32_t) len); + + return get_value; + } + + /* 5.c */ + ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, len, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_free_value (get_value); + return del_value; + } + + ecma_free_value (del_value); + + /* 5.d */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_free_value (get_value); + return set_length_value; + } + + return get_value; +} /* ecma_builtin_array_prototype_object_pop */ + +/** + * The Array.prototype object's 'push' routine + * + * See also: + * ECMA-262 v5, 15.4.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t length) /**< object's length */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + if ((ecma_number_t) (length + arguments_number) > UINT32_MAX) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + if (arguments_number == 0) + { + return ecma_make_uint32_value ((uint32_t) length); + } + + uint32_t new_length = ((uint32_t) length) + arguments_number; + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ecma_value_t *buffer_p = ecma_fast_array_extend (obj_p, new_length) + length; + + for (uint32_t index = 0; index < arguments_number; index++) + { + buffer_p[index] = ecma_copy_value_if_not_object (argument_list_p[index]); + } + + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE * arguments_number; + + return ecma_make_uint32_value (new_length); + } + + /* 5. */ + if ((ecma_number_t) (length + arguments_number) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_PUSHING_TOO_HIGH_ELEMENT); + } + + /* 6. */ + for (ecma_length_t index = 0; index < arguments_number; index++, length++) + { + /* 6.b */ + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, length, argument_list_p[index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + return put_value; + } + } + + /* 6 - 7. */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, (ecma_number_t) length); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + return set_length_value; + } + + return ecma_make_length_value (length); +} /* ecma_builtin_array_prototype_object_push */ + +/** + * The Array.prototype object's 'reverse' routine + * + * See also: + * ECMA-262 v5, 15.4.4.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this argument */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + uint32_t middle = (uint32_t) len / 2; + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0) + { + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + for (uint32_t i = 0; i < middle; i++) + { + ecma_value_t tmp = buffer_p[i]; + buffer_p[i] = buffer_p[len - 1 - i]; + buffer_p[len - 1 - i] = tmp; + } + + return ecma_copy_value (this_arg); + } + } + + ecma_length_t middle = len / 2; + for (ecma_length_t lower = 0; lower < middle; lower++) + { + ecma_length_t upper = len - lower - 1; + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + ecma_string_t *lower_str_p = ecma_new_ecma_string_from_length (lower); + ecma_string_t *upper_str_p = ecma_new_ecma_string_from_length (upper); + + ecma_value_t lower_value = ECMA_VALUE_EMPTY; + ecma_value_t upper_value = ECMA_VALUE_EMPTY; + + ecma_value_t has_lower = ecma_op_object_has_property (obj_p, lower_str_p); + ecma_value_t has_upper; + + bool upper_exist; + bool lower_exist; + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_lower)) + { + goto clean_up; + } +#endif /* JERRY_BUILTIN_PROXY */ + + lower_exist = ecma_is_value_true (has_lower); + + if (lower_exist) + { + lower_value = ecma_op_object_get (obj_p, lower_str_p); + + if (ECMA_IS_VALUE_ERROR (lower_value)) + { + goto clean_up; + } + } + + has_upper = ecma_op_object_has_property (obj_p, upper_str_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_upper)) + { + goto clean_up; + } +#endif /* JERRY_BUILTIN_PROXY */ + + upper_exist = ecma_is_value_true (has_upper); + + if (upper_exist) + { + upper_value = ecma_op_object_get (obj_p, upper_str_p); + + if (ECMA_IS_VALUE_ERROR (upper_value)) + { + goto clean_up; + } + } + + if (lower_exist && upper_exist) + { + ecma_value_t outer_put_value = ecma_op_object_put (obj_p, lower_str_p, upper_value, true); + + if (ECMA_IS_VALUE_ERROR (outer_put_value)) + { + goto clean_up; + } + + ecma_value_t inner_put_value = ecma_op_object_put (obj_p, upper_str_p, lower_value, true); + + if (ECMA_IS_VALUE_ERROR (inner_put_value)) + { + goto clean_up; + } + } + else if (!lower_exist && upper_exist) + { + ecma_value_t put_value = ecma_op_object_put (obj_p, lower_str_p, upper_value, true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + goto clean_up; + } + + ecma_value_t del_value = ecma_op_object_delete (obj_p, upper_str_p, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + goto clean_up; + } + } + else if (lower_exist) + { + ecma_value_t del_value = ecma_op_object_delete (obj_p, lower_str_p, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + goto clean_up; + } + + ecma_value_t put_value = ecma_op_object_put (obj_p, upper_str_p, lower_value, true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + goto clean_up; + } + } + + ret_value = ECMA_VALUE_EMPTY; + +clean_up: + ecma_free_value (upper_value); + ecma_free_value (lower_value); + ecma_deref_ecma_string (lower_str_p); + ecma_deref_ecma_string (upper_str_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + } + + return ecma_copy_value (this_arg); +} /* ecma_builtin_array_prototype_object_reverse */ + +/** + * The Array.prototype object's 'shift' routine + * + * See also: + * ECMA-262 v5, 15.4.4.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_shift (ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO); + + return ECMA_IS_VALUE_ERROR (set_length_value) ? set_length_value : ECMA_VALUE_UNDEFINED; + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0) + { + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + ecma_value_t ret_value = buffer_p[0]; + + if (ecma_is_value_object (ret_value)) + { + ecma_ref_object (ecma_get_object_from_value (ret_value)); + } + + memmove (buffer_p, buffer_p + 1, (size_t) (sizeof (ecma_value_t) * (len - 1))); + + buffer_p[len - 1] = ECMA_VALUE_UNDEFINED; + ecma_delete_fast_array_properties (obj_p, (uint32_t) (len - 1)); + + return ret_value; + } + } + + /* 5. */ + ecma_value_t first_value = ecma_op_object_get_by_index (obj_p, 0); + + if (ECMA_IS_VALUE_ERROR (first_value)) + { + return first_value; + } + + /* 6. and 7. */ + for (ecma_length_t k = 1; k < len; k++) + { + /* 7.a - 7.c */ + ecma_value_t curr_value = ecma_op_object_find_by_index (obj_p, k); + + if (ECMA_IS_VALUE_ERROR (curr_value)) + { + ecma_free_value (first_value); + return curr_value; + } + + /* 7.b */ + ecma_length_t to = k - 1; + ecma_value_t operation_value; + + if (ecma_is_value_found (curr_value)) + { + /* 7.d.i, 7.d.ii */ + operation_value = ecma_op_object_put_by_index (obj_p, to, curr_value, true); + ecma_free_value (curr_value); + } + else + { + /* 7.e.i */ + operation_value = ecma_op_object_delete_by_index (obj_p, to, true); + } + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + ecma_free_value (first_value); + return operation_value; + } + } + + /* 8. */ + ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, --len, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_free_value (first_value); + return del_value; + } + + /* 9. */ + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_free_value (first_value); + return set_length_value; + } + + /* 10. */ + return first_value; +} /* ecma_builtin_array_prototype_object_shift */ + +/** + * The Array.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v5, 15.4.4.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */ + ecma_value_t arg2, /**< end */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t start = 0, end = len; + + /* 5. 6.*/ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg1, len, &start))) + { + return ECMA_VALUE_ERROR; + } + + /* 7. */ + if (ecma_is_value_undefined (arg2)) + { + end = len; + } + else + { + /* 7. part 2, 8.*/ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg2, len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + + JERRY_ASSERT (start <= len && end <= len); + + bool use_fast_path = ecma_op_object_is_fast_array (obj_p); + ecma_length_t copied_length = (end > start) ? end - start : 0; + + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, copied_length); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + use_fast_path &= ecma_op_object_is_fast_array (new_array_p); + + if (use_fast_path && copied_length > 0) + { + ecma_extended_object_t *ext_from_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_from_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + /** + * Very unlikely case: the buffer copied from is a fast buffer and the property list was deleted. + * There is no need to do any copy. + */ + return ecma_make_object_value (new_array_p); + } + + /* Source array's length could be changed during the start/end normalization. + * If the "end" value is greater than the current length, clamp the value to avoid buffer-overflow. */ + if (ext_from_obj_p->u.array.length < end) + { + end = ext_from_obj_p->u.array.length; + } + + ecma_extended_object_t *ext_to_obj_p = (ecma_extended_object_t *) new_array_p; + + uint32_t target_length = ext_to_obj_p->u.array.length; + ecma_value_t *to_buffer_p; + JERRY_ASSERT (copied_length <= UINT32_MAX); + + if (copied_length == target_length) + { + to_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, new_array_p->u1.property_list_cp); + } + else if (copied_length > target_length) + { + to_buffer_p = ecma_fast_array_extend (new_array_p, (uint32_t) copied_length); + } + else + { + ecma_delete_fast_array_properties (new_array_p, (uint32_t) copied_length); + to_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, new_array_p->u1.property_list_cp); + } + + ecma_value_t *from_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + /* 9. */ + uint32_t n = 0; + + for (uint32_t k = (uint32_t) start; k < (uint32_t) end; k++, n++) + { + ecma_free_value_if_not_object (to_buffer_p[n]); + to_buffer_p[n] = ecma_copy_value_if_not_object (from_buffer_p[k]); + } + + ext_to_obj_p->u.array.length_prop_and_hole_count &= ECMA_FAST_ARRAY_HOLE_ONE - 1; + + return ecma_make_object_value (new_array_p); + } + } + + /* 9. */ + ecma_length_t n = 0; + + /* 10. */ + for (ecma_length_t k = start; k < end; k++, n++) + { + /* 10.c */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, k); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + ecma_deref_object (new_array_p); + return get_value; + } + + if (ecma_is_value_found (get_value)) + { + /* 10.c.ii */ + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + n, + get_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | JERRY_PROP_SHOULD_THROW); + ecma_free_value (get_value); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_deref_object (new_array_p); + return put_comp; + } + } + } + + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) n)); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + ecma_deref_object (new_array_p); + return set_length_value; + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_slice */ + +/** + * SortCompare abstract method + * + * See also: + * ECMA-262 v5, 15.4.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_sort_compare_helper (ecma_value_t lhs, /**< left value */ + ecma_value_t rhs, /**< right value */ + ecma_value_t compare_func, /**< compare function */ + ecma_object_t *array_buffer_p) /**< arrayBuffer */ +{ + JERRY_UNUSED (array_buffer_p); + /* + * ECMA-262 v5, 15.4.4.11 NOTE1: Because non-existent property values always + * compare greater than undefined property values, and undefined always + * compares greater than any other value, undefined property values always + * sort to the end of the result, followed by non-existent property values. + */ + bool lhs_is_undef = ecma_is_value_undefined (lhs); + bool rhs_is_undef = ecma_is_value_undefined (rhs); + + if (lhs_is_undef) + { + return ecma_make_integer_value (rhs_is_undef ? 0 : 1); + } + + if (rhs_is_undef) + { + return ecma_make_integer_value (-1); + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + + if (ecma_is_value_undefined (compare_func)) + { + /* Default comparison when no compare_func is passed. */ + ecma_string_t *lhs_str_p = ecma_op_to_string (lhs); + if (JERRY_UNLIKELY (lhs_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *rhs_str_p = ecma_op_to_string (rhs); + if (JERRY_UNLIKELY (rhs_str_p == NULL)) + { + ecma_deref_ecma_string (lhs_str_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_compare_ecma_strings_relational (lhs_str_p, rhs_str_p)) + { + result = ECMA_NUMBER_MINUS_ONE; + } + else if (!ecma_compare_ecma_strings (lhs_str_p, rhs_str_p)) + { + result = ECMA_NUMBER_ONE; + } + else + { + result = ECMA_NUMBER_ZERO; + } + + ecma_deref_ecma_string (rhs_str_p); + ecma_deref_ecma_string (lhs_str_p); + } + else + { + /* + * compare_func, if not undefined, will always contain a callable function object. + * We checked this previously, before this function was called. + */ + JERRY_ASSERT (ecma_op_is_callable (compare_func)); + ecma_object_t *comparefn_obj_p = ecma_get_object_from_value (compare_func); + + ecma_value_t compare_args[] = { lhs, rhs }; + + ecma_value_t call_value = ecma_op_function_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + if (!ecma_is_value_number (call_value)) + { + ecma_number_t ret_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (call_value, &ret_num))) + { + ecma_free_value (call_value); + return ECMA_VALUE_ERROR; + } + + result = ret_num; + } + else + { + result = ecma_get_number_from_value (call_value); + } + + ecma_free_value (call_value); + } + + return ecma_make_number_value (result); +} /* ecma_builtin_array_prototype_object_sort_compare_helper */ + +/** + * The Array.prototype object's 'sort' routine + * + * See also: + * ECMA-262 v5, 15.4.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg1, /**< comparefn */ + ecma_object_t *obj_p) /**< object */ +{ + /* Check if the provided compare function is callable. */ + if (!ecma_is_value_undefined (arg1) && !ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_COMPARE_FUNC_NOT_CALLABLE); + } + + ecma_length_t len; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &len); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + return len_value; + } + ecma_collection_t *array_index_props_p = ecma_new_collection (); + + for (uint32_t i = 0; i < len; i++) + { + ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); + + ecma_property_descriptor_t prop_desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + ecma_collection_free (array_index_props_p); + ecma_deref_ecma_string (prop_name_p); + return get_desc; + } + + if (ecma_is_value_true (get_desc)) + { + ecma_ref_ecma_string (prop_name_p); + ecma_collection_push_back (array_index_props_p, ecma_make_string_value (prop_name_p)); + ecma_free_property_descriptor (&prop_desc); + continue; + } + } + + uint32_t defined_prop_count = array_index_props_p->item_count; + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + uint32_t copied_num = 0; + JMEM_DEFINE_LOCAL_ARRAY (values_buffer, defined_prop_count, ecma_value_t); + + ecma_value_t *buffer_p = array_index_props_p->buffer_p; + + /* Copy unsorted array into a native c array. */ + for (uint32_t i = 0; i < array_index_props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); + + uint32_t index = ecma_string_get_array_index (property_name_p); + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + + if (index >= len) + { + break; + } + + ecma_value_t index_value = ecma_op_object_get (obj_p, property_name_p); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + goto clean_up; + } + + values_buffer[copied_num++] = index_value; + } + + JERRY_ASSERT (copied_num == defined_prop_count); + + /* Sorting. */ + if (copied_num > 1) + { + const ecma_builtin_helper_sort_compare_fn_t sort_cb = &ecma_builtin_array_prototype_object_sort_compare_helper; + ecma_value_t sort_value = + ecma_builtin_helper_array_merge_sort_helper (values_buffer, (uint32_t) (copied_num), arg1, sort_cb, NULL); + if (ECMA_IS_VALUE_ERROR (sort_value)) + { + goto clean_up; + } + + ecma_free_value (sort_value); + } + + /* Put sorted values to the front of the array. */ + for (uint32_t index = 0; index < copied_num; index++) + { + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, index, values_buffer[index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + goto clean_up; + } + } + + ret_value = ECMA_VALUE_EMPTY; + +clean_up: + /* Free values that were copied to the local array. */ + for (uint32_t index = 0; index < copied_num; index++) + { + ecma_free_value (values_buffer[index]); + } + + JMEM_FINALIZE_LOCAL_ARRAY (values_buffer); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_collection_free (array_index_props_p); + return ret_value; + } + + JERRY_ASSERT (ecma_is_value_empty (ret_value)); + + /* Undefined properties should be in the back of the array. */ + ecma_value_t *buffer_p = array_index_props_p->buffer_p; + + for (uint32_t i = 0; i < array_index_props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); + + uint32_t index = ecma_string_get_array_index (property_name_p); + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + + if (index >= copied_num && index < len) + { + ecma_value_t del_value = ecma_op_object_delete (obj_p, property_name_p, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_collection_free (array_index_props_p); + return del_value; + } + } + } + + ecma_collection_free (array_index_props_p); + + return ecma_copy_value (this_arg); +} /* ecma_builtin_array_prototype_object_sort */ + +/** + * The Array.prototype object's 'splice' routine + * + * See also: + * ECMA-262 v11, 22.1.3.28 + * ECMA-262 v5, 15.4.4.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t actual_start = 0; + ecma_length_t actual_delete_count = 0; + ecma_length_t insert_count = 0; + + if (args_number > 0) + { + /* ES5.1: 6, ES11: 4. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0], len, &actual_start))) + { + return ECMA_VALUE_ERROR; + } + + /* ES11: 6. */ + if (args_number == 1) + { + actual_delete_count = len - actual_start; + } + /* ES11: 7. */ + else + { + insert_count = args_number - 2; + + ecma_number_t delete_num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &delete_num))) + { + return ECMA_VALUE_ERROR; + } + + /* ES5.1: 7 */ + actual_delete_count = + (ecma_length_t) (JERRY_MIN (JERRY_MAX (delete_num, 0), (ecma_number_t) (len - actual_start))); + } + } + + ecma_length_t new_length = len + insert_count - actual_delete_count; + + /* ES11: 8. */ + if ((ecma_number_t) new_length > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_INVALID_NEW_ARRAY_LENGTH); + } + + /* ES11: 9. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, actual_delete_count); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* ES5.1: 8, ES11: 10. */ + ecma_length_t k = 0; + + /* ES5.1: 9, ES11: 11. */ + for (; k < actual_delete_count; k++) + { + ecma_length_t from = actual_start + k; + ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from); + + if (ECMA_IS_VALUE_ERROR (from_present)) + { + ecma_deref_object (new_array_p); + return from_present; + } + + if (ecma_is_value_found (from_present)) + { + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + k, + from_present, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | JERRY_PROP_SHOULD_THROW); + ecma_free_value (from_present); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_deref_object (new_array_p); + return put_comp; + } + } + } + + /* ES11: 12. */ + ecma_value_t set_length = + ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) actual_delete_count)); + + if (ECMA_IS_VALUE_ERROR (set_length)) + { + ecma_deref_object (new_array_p); + return set_length; + } + + /* ES5.1: 12, ES11: 15. */ + if (insert_count < actual_delete_count) + { + for (k = actual_start; k < len - actual_delete_count; k++) + { + ecma_length_t from = k + actual_delete_count; + ecma_length_t to = k + insert_count; + + ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from); + + if (ECMA_IS_VALUE_ERROR (from_present)) + { + ecma_deref_object (new_array_p); + return from_present; + } + + ecma_value_t operation_value; + + if (ecma_is_value_found (from_present)) + { + operation_value = ecma_op_object_put_by_index (obj_p, to, from_present, true); + ecma_free_value (from_present); + } + else + { + operation_value = ecma_op_object_delete_by_index (obj_p, to, true); + } + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + ecma_deref_object (new_array_p); + return operation_value; + } + } + + k = len; + + for (k = len; k > new_length; k--) + { + ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, k - 1, true); + + if (ECMA_IS_VALUE_ERROR (del_value)) + { + ecma_deref_object (new_array_p); + return del_value; + } + } + } + /* ES5.1: 13, ES11: 16. */ + else if (insert_count > actual_delete_count) + { + for (k = len - actual_delete_count; k > actual_start; k--) + { + ecma_length_t from = k + actual_delete_count - 1; + ecma_length_t to = k + insert_count - 1; + + ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from); + + if (ECMA_IS_VALUE_ERROR (from_present)) + { + ecma_deref_object (new_array_p); + return from_present; + } + + ecma_value_t operation_value; + + if (ecma_is_value_found (from_present)) + { + operation_value = ecma_op_object_put_by_index (obj_p, to, from_present, true); + ecma_free_value (from_present); + } + else + { + operation_value = ecma_op_object_delete_by_index (obj_p, to, true); + } + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + ecma_deref_object (new_array_p); + return operation_value; + } + } + } + + /* ES5.1: 14, ES11: 17. */ + k = actual_start; + + /* ES5.1: 15, ES11: 18. */ + uint32_t idx = 0; + for (uint32_t arg_index = 2; arg_index < args_number; arg_index++, idx++) + { + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, actual_start + idx, args[arg_index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + ecma_deref_object (new_array_p); + return put_value; + } + } + + /* ES5.1: 16, ES11: 19. */ + ecma_value_t set_new_length = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) new_length)); + + if (ECMA_IS_VALUE_ERROR (set_new_length)) + { + ecma_deref_object (new_array_p); + return set_new_length; + } + + /* ES5.1: 17, ES11: 20. */ + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_splice */ + +/** + * The Array.prototype object's 'unshift' routine + * + * See also: + * ECMA-262 v5, 15.4.4.13 + * ECMA-262 v11, 22.1.3.31 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0) + { + if (args_number > UINT32_MAX - len) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + if (args_number == 0) + { + return ecma_make_uint32_value ((uint32_t) len); + } + + uint32_t new_length = ((uint32_t) len) + args_number; + ecma_value_t *buffer_p = ecma_fast_array_extend (obj_p, new_length); + memmove (buffer_p + args_number, buffer_p, (size_t) (sizeof (ecma_value_t) * len)); + + uint32_t index = 0; + + while (index < args_number) + { + buffer_p[index] = ecma_copy_value_if_not_object (args[index]); + index++; + } + + ext_obj_p->u.array.length_prop_and_hole_count -= args_number * ECMA_FAST_ARRAY_HOLE_ONE; + + return ecma_make_uint32_value (new_length); + } + } + + if (args_number > 0) + { + /* ES11:4.a. */ + if ((ecma_number_t) (len + args_number) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_UNSHIFT_TOO_HIGH); + } + + /* ES5.1:5.,6. ES11: 4.b, 4.c */ + for (ecma_length_t k = len; k > 0; k--) + { + /* ES5.1:6.a, 6.c, ES11:4.c.i., 4.c.iii. */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, k - 1); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* ES5.1:6.b, ES11:4.c.ii. */ + ecma_number_t new_idx = ((ecma_number_t) k) + ((ecma_number_t) args_number) - 1; + ecma_string_t *index_str_p = ecma_new_ecma_string_from_number (new_idx); + ecma_value_t operation_value; + + if (ecma_is_value_found (get_value)) + { + /* ES5.1:6.d.i, 6.d.ii, ES11:4.c.iv. */ + operation_value = ecma_op_object_put (obj_p, index_str_p, get_value, true); + ecma_free_value (get_value); + } + else + { + /* ES5.1:6.e.i, ES11:4.c.v. */ + operation_value = ecma_op_object_delete (obj_p, index_str_p, true); + } + + ecma_deref_ecma_string (index_str_p); + + if (ECMA_IS_VALUE_ERROR (operation_value)) + { + return operation_value; + } + } + + for (uint32_t arg_index = 0; arg_index < args_number; arg_index++) + { + /* ES5.1:9.b, ES11:4.f.ii. */ + ecma_value_t put_value = ecma_op_object_put_by_index (obj_p, arg_index, args[arg_index], true); + + if (ECMA_IS_VALUE_ERROR (put_value)) + { + return put_value; + } + } + } + + /* ES5.1:10., ES11:5. */ + ecma_number_t new_len = ((ecma_number_t) len) + ((ecma_number_t) args_number); + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, new_len); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + return set_length_value; + } + + return ecma_make_number_value (new_len); +} /* ecma_builtin_array_prototype_object_unshift */ + +/** + * The Array.prototype object's 'at' routine + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal + * from: https://tc39.es/proposal-relative-indexing-method + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_at (const ecma_value_t index, /**< index argument */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t res_index; + ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index); + + if (return_value != ECMA_VALUE_EMPTY) + { + return return_value; + } + + return ecma_op_object_get_by_index (obj_p, res_index); +} /* ecma_builtin_array_prototype_object_at */ + +/** + * The Array.prototype object's 'indexOf' routine + * + * See also: + * ECMA-262 v5, 15.4.4.14 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_index_of (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + return ecma_make_integer_value (-1); + } + + /* 5. */ + ecma_number_t idx = 0; + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &idx))) + { + return ECMA_VALUE_ERROR; + } + } + + /* 6. */ + if (idx >= (ecma_number_t) len) + { + return ecma_make_number_value (-1); + } + + /* 7. */ + ecma_length_t from_idx = (ecma_length_t) idx; + + /* 8. */ + if (idx < 0) + { + from_idx = (ecma_length_t) JERRY_MAX ((ecma_number_t) len + idx, 0); + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + return ecma_make_integer_value (-1); + } + + len = JERRY_MIN (ext_obj_p->u.array.length, len); + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (from_idx < len) + { + if (ecma_op_strict_equality_compare (args[0], buffer_p[from_idx])) + { + return ecma_make_uint32_value ((uint32_t) from_idx); + } + + from_idx++; + } + + return ecma_make_integer_value (-1); + } + } + + /* 6. */ + while (from_idx < len) + { + /* 9.a */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, from_idx); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* 9.b.i, 9.b.ii */ + if (ecma_is_value_found (get_value) && ecma_op_strict_equality_compare (args[0], get_value)) + { + ecma_free_value (get_value); + return ecma_make_length_value (from_idx); + } + + from_idx++; + + ecma_free_value (get_value); + } + + return ecma_make_integer_value (-1); +} /* ecma_builtin_array_prototype_object_index_of */ + +/** + * The Array.prototype object's 'lastIndexOf' routine + * + * See also: + * ECMA-262 v5, 15.4.4.15 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (len == 0) + { + return ecma_make_integer_value (-1); + } + + /* 5. */ + ecma_number_t idx = (ecma_number_t) len - 1; + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &idx))) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_length_t from_idx; + + /* 6 */ + if (idx >= 0) + { + from_idx = (ecma_length_t) (JERRY_MIN (idx, (ecma_number_t) (len - 1))); + } + else + { + ecma_number_t k = (ecma_number_t) len + idx; + if (k < 0) + { + return ecma_make_integer_value (-1); + } + from_idx = (ecma_length_t) k; + } + + ecma_value_t search_element = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED; + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + return ecma_make_integer_value (-1); + } + + len = JERRY_MIN (ext_obj_p->u.array.length, len); + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (from_idx < len) + { + if (ecma_op_strict_equality_compare (search_element, buffer_p[from_idx])) + { + return ecma_make_uint32_value ((uint32_t) from_idx); + } + from_idx--; + } + return ecma_make_integer_value (-1); + } + } + + /* 8. */ + while (from_idx < len) + { + /* 8.a */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, from_idx); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* 8.b.i, 8.b.ii */ + if (ecma_is_value_found (get_value) && ecma_op_strict_equality_compare (search_element, get_value)) + { + ecma_free_value (get_value); + return ecma_make_length_value (from_idx); + } + + from_idx--; + + ecma_free_value (get_value); + } + + return ecma_make_integer_value (-1); +} /* ecma_builtin_array_prototype_object_last_index_of */ + +/** + * Type of array routine. + */ +typedef enum +{ + ARRAY_ROUTINE_EVERY, /**< Array.every: ECMA-262 v5, 15.4.4.16 */ + ARRAY_ROUTINE_SOME, /**< Array.some: ECMA-262 v5, 15.4.4.17 */ + ARRAY_ROUTINE_FOREACH, /**< Array.forEach: ECMA-262 v5, 15.4.4.18 */ + ARRAY_ROUTINE__COUNT /**< count of the modes */ +} array_routine_mode; + +/** + * Applies the provided function to each element of the array as long as + * the return value stays empty. The common function for 'every', 'some' + * and 'forEach' of the Array prototype. + * + * See also: + * ECMA-262 v5, 15.4.4.16 + * ECMA-262 v5, 15.4.4.17 + * ECMA-262 v5, 15.4.4.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_apply (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + array_routine_mode mode, /**< array routine mode */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ + +{ + JERRY_ASSERT (mode < ARRAY_ROUTINE__COUNT); + + /* 4. */ + if (!ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* We already checked that arg1 is callable */ + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + ecma_value_t current_index; + + /* 7. */ + for (ecma_length_t index = 0; index < len; index++) + { + /* 7.a - 7.c */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + if (ecma_is_value_found (get_value)) + { + /* 7.c.i */ + current_index = ecma_make_length_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + /* 7.c.ii */ + ecma_value_t call_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (get_value); + return call_value; + } + + bool to_boolean = ecma_op_to_boolean (call_value); + + ecma_free_value (call_value); + ecma_free_value (get_value); + + /* 7.c.iii */ + if (mode == ARRAY_ROUTINE_EVERY && !to_boolean) + { + return ECMA_VALUE_FALSE; + } + else if (mode == ARRAY_ROUTINE_SOME && to_boolean) + { + return ECMA_VALUE_TRUE; + } + } + } + + /* 8. */ + + if (mode == ARRAY_ROUTINE_EVERY) + { + return ECMA_VALUE_TRUE; + } + else if (mode == ARRAY_ROUTINE_SOME) + { + return ECMA_VALUE_FALSE; + } + + JERRY_ASSERT (mode == ARRAY_ROUTINE_FOREACH); + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_array_apply */ + +/** + * The Array.prototype object's 'map' routine + * + * See also: + * ECMA-262 v5, 15.4.4.19 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_map (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (!ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 6. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, len); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + JERRY_ASSERT (ecma_is_value_object (arg1)); + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + + /* 7-8. */ + ecma_value_t current_index; + + for (ecma_length_t index = 0; index < len; index++) + { + /* 8.a - 8.b */ + ecma_value_t current_value = ecma_op_object_find_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (current_value)) + { + ecma_deref_object (new_array_p); + return current_value; + } + + if (ecma_is_value_found (current_value)) + { + /* 8.c.i, 8.c.ii */ + current_index = ecma_make_length_value (index); + ecma_value_t call_args[] = { current_value, current_index, ecma_make_object_value (obj_p) }; + + ecma_value_t mapped_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + ecma_free_value (current_value); + ecma_deref_object (new_array_p); + return mapped_value; + } + + /* 8.c.iii */ + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + index, + mapped_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | JERRY_PROP_SHOULD_THROW); + + ecma_free_value (mapped_value); + ecma_free_value (current_value); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_deref_object (new_array_p); + return put_comp; + } + } + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_map */ + +/** + * The Array.prototype object's 'filter' routine + * + * See also: + * ECMA-262 v5, 15.4.4.20 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_filter (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (!ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 6. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* ES11: 22.1.3.7. 7.c.iii.1 */ + const uint32_t prop_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + /* We already checked that arg1 is callable, so it will always be an object. */ + JERRY_ASSERT (ecma_is_value_object (arg1)); + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + + /* 8. */ + ecma_length_t new_array_index = 0; + ecma_value_t current_index; + + /* 9. */ + for (ecma_length_t index = 0; index < len; index++) + { + /* 9.a - 9.c */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + ecma_deref_object (new_array_p); + return get_value; + } + + if (ecma_is_value_found (get_value)) + { + /* 9.c.i */ + current_index = ecma_make_length_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + /* 9.c.ii */ + ecma_value_t call_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (get_value); + ecma_deref_object (new_array_p); + return call_value; + } + + /* 9.c.iii */ + if (ecma_op_to_boolean (call_value)) + { + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, new_array_index, get_value, prop_flags); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + ecma_free_value (call_value); + ecma_free_value (get_value); + ecma_deref_object (new_array_p); + + return put_comp; + } + + new_array_index++; + } + + ecma_free_value (call_value); + ecma_free_value (get_value); + } + } + + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_filter */ + +/** + * The Array.prototype object's 'reduce' and 'reduceRight' routine + * + * See also: + * ECMA-262 v5, 15.4.4.21 + * ECMA-262 v5, 15.4.4.22 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_reduce_from (const ecma_value_t args_p[], /**< routine's arguments */ + uint32_t args_number, /**< arguments list length */ + bool start_from_left, /**< whether the reduce starts from left or right */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 4. */ + if (!ecma_op_is_callable (args_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 5. */ + if (len == 0 && args_number == 1) + { + return ecma_raise_type_error (ECMA_ERR_REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE); + } + + JERRY_ASSERT (ecma_is_value_object (args_p[0])); + ecma_object_t *func_object_p = ecma_get_object_from_value (args_p[0]); + + ecma_value_t accumulator = ECMA_VALUE_UNDEFINED; + + /* 6. */ + ecma_length_t index = 0; + const ecma_length_t last_index = len - 1; + + /* 7.a */ + if (args_number > 1) + { + accumulator = ecma_copy_value (args_p[1]); + } + else + { + /* 8.a */ + bool k_present = false; + + /* 8.b */ + while (!k_present && index < len) + { + /* 8.b.i */ + k_present = true; + + /* 8.b.ii-iii */ + ecma_value_t current_value = ecma_op_object_find_by_index (obj_p, start_from_left ? index : last_index - index); + + if (ECMA_IS_VALUE_ERROR (current_value)) + { + return current_value; + } + + if (ecma_is_value_found (current_value)) + { + accumulator = current_value; + } + else + { + k_present = false; + } + + /* 8.b.iv */ + index++; + } + + /* 8.c */ + if (!k_present) + { + return ecma_raise_type_error (ECMA_ERR_MISSING_ARRAY_ELEMENT); + } + } + /* 9. */ + ecma_value_t current_index; + + for (; index < len; index++) + { + const ecma_length_t corrected_index = start_from_left ? index : last_index - index; + + /* 9.a - 9.b */ + ecma_value_t current_value = ecma_op_object_find_by_index (obj_p, corrected_index); + + if (ECMA_IS_VALUE_ERROR (current_value)) + { + ecma_free_value (accumulator); + return current_value; + } + + if (ecma_is_value_found (current_value)) + { + /* 9.c.i, 9.c.ii */ + current_index = ecma_make_length_value (corrected_index); + ecma_value_t call_args[] = { accumulator, current_value, current_index, ecma_make_object_value (obj_p) }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); + ecma_free_value (current_index); + ecma_free_value (accumulator); + ecma_free_value (current_value); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + accumulator = call_value; + } + } + + return accumulator; +} /* ecma_builtin_array_reduce_from */ + +/** + * The Array.prototype object's 'fill' routine + * + * Note: this method only supports length up to uint32, instead of max_safe_integer + * + * See also: + * ECMA-262 v6, 22.1.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_fill (ecma_value_t value, /**< value */ + ecma_value_t start_val, /**< start value */ + ecma_value_t end_val, /**< end value */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + ecma_length_t k, final; + + /* 5. 6. 7. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (start_val, len, &k))) + { + return ECMA_VALUE_ERROR; + } + + /* 8. */ + if (ecma_is_value_undefined (end_val)) + { + final = len; + } + else + { + /* 8 part 2, 9, 10 */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (end_val, len, &final))) + { + return ECMA_VALUE_ERROR; + } + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) + { + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (k < final) + { + ecma_free_value_if_not_object (buffer_p[k]); + buffer_p[k] = ecma_copy_value_if_not_object (value); + k++; + } + + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + } + + /* 11. */ + while (k < final) + { + /* 11.a - 11.b */ + ecma_value_t put_val = ecma_op_object_put_by_index (obj_p, k, value, true); + + /* 11. c */ + if (ECMA_IS_VALUE_ERROR (put_val)) + { + return put_val; + } + + /* 11.d */ + k++; + } + + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); +} /* ecma_builtin_array_prototype_fill */ + +/** + * The Array.prototype object's 'find' and 'findIndex' routine + * + * See also: + * ECMA-262 v6, 22.1.3.8 + * ECMA-262 v6, 22.1.3.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_find (ecma_value_t predicate, /**< callback function */ + ecma_value_t predicate_this_arg, /**< this argument for + * invoke predicate */ + bool is_find, /**< true - find routine + * false - findIndex routine */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 5. */ + if (!ecma_op_is_callable (predicate)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* We already checked that predicate is callable, so it will always be an object. */ + JERRY_ASSERT (ecma_is_value_object (predicate)); + ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); + + /* 7 - 8. */ + for (ecma_length_t index = 0; index < len; index++) + { + /* 8.a - 8.c */ + ecma_value_t get_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + /* 8.d - 8.e */ + ecma_value_t current_index = ecma_make_length_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (get_value); + return call_value; + } + + bool call_value_to_bool = ecma_op_to_boolean (call_value); + + ecma_free_value (call_value); + + if (call_value_to_bool) + { + /* 8.f */ + if (is_find) + { + ecma_free_value (current_index); + return get_value; + } + + ecma_free_value (get_value); + return current_index; + } + + ecma_free_value (get_value); + ecma_free_value (current_index); + } + + /* 9. */ + return is_find ? ECMA_VALUE_UNDEFINED : ecma_make_integer_value (-1); +} /* ecma_builtin_array_prototype_object_find */ + +/** + * The Array.prototype object's 'copyWithin' routine + * + * See also: + * ECMA-262 v6, 22.1.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_copy_within (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + if (args_number == 0) + { + return ecma_copy_value (ecma_make_object_value (obj_p)); + } + + /* 5 - 7 */ + ecma_length_t target; + + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0], len, &target))) + { + return ECMA_VALUE_ERROR; + } + + ecma_length_t start = 0; + ecma_length_t end = len; + + if (args_number > 1) + { + /* 8 - 10 */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1], len, &start))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 2) + { + /* 11 */ + if (ecma_is_value_undefined (args[2])) + { + end = len; + } + else + { + /* 11 part 2, 12, 13 */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[2], len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + } + } + + ecma_length_t count = JERRY_MIN (end - start, len - target); + if (end <= start || len <= target) /* count <= 0 check, but variables are unsigned */ + { + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + + bool forward = true; + + if (start < target && target < start + count) + { + start = start + count - 1; + target = target + count - 1; + forward = false; + } + + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + const uint32_t actual_length = ext_obj_p->u.array.length; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE + && ((forward && (target + count - 1 < actual_length)) || (!forward && (target < actual_length)))) + { + if (obj_p->u1.property_list_cp != JMEM_CP_NULL) + { + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + for (; count > 0; count--) + { + ecma_value_t copy_value = ecma_copy_value_if_not_object (buffer_p[start]); + + ecma_free_value_if_not_object (buffer_p[target]); + + buffer_p[target] = copy_value; + + if (forward) + { + start++; + target++; + } + else + { + start--; + target--; + } + } + } + + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); + } + } + + while (count > 0) + { + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, start); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + ecma_value_t op_value; + + if (ecma_is_value_found (get_value)) + { + op_value = ecma_op_object_put_by_index (obj_p, target, get_value, true); + } + else + { + op_value = ecma_op_object_delete_by_index (obj_p, target, true); + } + + ecma_free_value (get_value); + + if (ECMA_IS_VALUE_ERROR (op_value)) + { + return op_value; + } + + ecma_free_value (op_value); + + if (forward) + { + start++; + target++; + } + else + { + start--; + target--; + } + + count--; + } + + return ecma_copy_value (ecma_make_object_value (obj_p)); +} /* ecma_builtin_array_prototype_object_copy_within */ + +/** + * The Array.prototype object's 'includes' routine + * + * See also: + * ECMA-262 v11, 22.1.3.13 + * + * @return ECMA_VALUE_ERROR -if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the search element is in the array or not + */ +static ecma_value_t +ecma_builtin_array_prototype_includes (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< object */ + ecma_length_t len) /**< object's length */ +{ + /* 3. */ + if (len == 0) + { + return ECMA_VALUE_FALSE; + } + + ecma_length_t from_index = 0; + + /* 4-7. */ + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1], len, &from_index))) + { + return ECMA_VALUE_ERROR; + } + } + + /* Fast array path */ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + { + if (obj_p->u1.property_list_cp != JMEM_CP_NULL) + { + len = JERRY_MIN (ext_obj_p->u.array.length, len); + + ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + while (from_index < len) + { + if (ecma_op_same_value_zero (buffer_p[from_index], args[0], false)) + { + return ECMA_VALUE_TRUE; + } + + from_index++; + } + } + + return ECMA_VALUE_FALSE; + } + } + + /* 8. */ + while (from_index < len) + { + ecma_value_t element = ecma_op_object_get_by_index (obj_p, from_index); + + if (ECMA_IS_VALUE_ERROR (element)) + { + return element; + } + + if (ecma_op_same_value_zero (element, args[0], false)) + { + ecma_free_value (element); + return ECMA_VALUE_TRUE; + } + + ecma_free_value (element); + from_index++; + } + + /* 9. */ + return ECMA_VALUE_FALSE; +} /* ecma_builtin_array_prototype_includes */ + +/** + * Abstract operation: FlattenIntoArray + * + * See also: + * ECMA-262 v10, 22.1.3.10.1 + * + * @return ECMA_VALUE_ERROR -if the operation fails + * ecma value which contains target_index + */ +static ecma_value_t +ecma_builtin_array_flatten_into_array (ecma_value_t target, /**< target will contains source's elements */ + ecma_object_t *source, /**< source object */ + ecma_length_t source_len, /**< source object length */ + ecma_length_t start, /**< remaining recursion depth */ + ecma_number_t depth, /**< start index offset */ + ecma_value_t mapped_value, /**< mapped value */ + ecma_value_t thisArg) /**< this arg */ +{ + ECMA_CHECK_STACK_USAGE (); + + /* 7. */ + ecma_length_t target_index = start; + + /* 9. */ + for (ecma_length_t source_index = 0; source_index < source_len; source_index++) + { + /* a. */ + ecma_value_t element = ecma_op_object_find_by_index (source, source_index); + + if (ECMA_IS_VALUE_ERROR (element)) + { + return element; + } + + if (!ecma_is_value_found (element)) + { + continue; + } + + /* b-c. */ + if (!ecma_is_value_undefined (mapped_value)) + { + /* i-ii. */ + ecma_value_t source_val = ecma_make_length_value (source_index); + ecma_value_t args[] = { element, source_val, ecma_make_object_value (source) }; + ecma_value_t temp_element = ecma_op_function_call (ecma_get_object_from_value (mapped_value), thisArg, args, 3); + + ecma_free_value (element); + ecma_free_value (source_val); + + if (ECMA_IS_VALUE_ERROR (temp_element)) + { + return temp_element; + } + + element = temp_element; + } + + /* iv-v. */ + if (depth > 0) + { + ecma_value_t is_array = ecma_is_value_array (element); + + if (ECMA_IS_VALUE_ERROR (is_array)) + { + ecma_free_value (element); + return is_array; + } + + if (ecma_is_value_true (is_array)) + { + ecma_object_t *element_obj = ecma_get_object_from_value (element); + ecma_length_t element_len; + ecma_value_t len_value = ecma_op_object_get_length (element_obj, &element_len); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (element_obj); + return len_value; + } + + ecma_value_t target_index_val = ecma_builtin_array_flatten_into_array (target, + element_obj, + element_len, + target_index, + depth - 1, + ECMA_VALUE_UNDEFINED, + ECMA_VALUE_UNDEFINED); + + ecma_deref_object (element_obj); + + if (ECMA_IS_VALUE_ERROR (target_index_val)) + { + return target_index_val; + } + + target_index = (ecma_length_t) ecma_get_number_from_value (target_index_val); + continue; + } + } + + /* vi. */ + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + ecma_value_t element_temp = + ecma_builtin_helper_def_prop_by_index (ecma_get_object_from_value (target), target_index, element, flags); + + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (element_temp)) + { + return element_temp; + } + + target_index++; + } + /* 10. */ + return ecma_make_length_value (target_index); +} /* ecma_builtin_array_flatten_into_array */ + +/** + * The Array.prototype object's 'flat' routine + * + * See also: + * ECMA-262 v10, 22.1.3.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_flat (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< array object */ + ecma_length_t len) /**< array object's length */ +{ + /* 3. */ + ecma_number_t depth_num = 1; + + /* 4. */ + if (args_number > 0 && ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[0], &depth_num))) + { + return ECMA_VALUE_ERROR; + } + + /* 5. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_value_t flatten_val = ecma_builtin_array_flatten_into_array (ecma_make_object_value (new_array_p), + obj_p, + len, + 0, + depth_num, + ECMA_VALUE_UNDEFINED, + ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (flatten_val)) + { + ecma_deref_object (new_array_p); + return flatten_val; + } + + /* 7. */ + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_flat */ + +/** + * The Array.prototype object's 'flatMap' routine + * + * See also: + * ECMA-262 v10, 22.1.3.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_prototype_object_flat_map (ecma_value_t callback, /**< callbackFn */ + ecma_value_t this_arg, /**< thisArg */ + ecma_object_t *obj_p, /**< array object */ + ecma_length_t len) /**< array object's length */ +{ + if (!ecma_op_is_callable (callback)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 4. */ + ecma_object_t *new_array_p = ecma_op_array_species_create (obj_p, 0); + + if (JERRY_UNLIKELY (new_array_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 5. */ + ecma_value_t flatten_val = + ecma_builtin_array_flatten_into_array (ecma_make_object_value (new_array_p), obj_p, len, 0, 1, callback, this_arg); + if (ECMA_IS_VALUE_ERROR (flatten_val)) + { + ecma_deref_object (new_array_p); + return flatten_val; + } + + /* 6. */ + return ecma_make_object_value (new_array_p); +} /* ecma_builtin_array_prototype_object_flat_map */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_array_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_value_t obj_this = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (obj_this)) + { + return obj_this; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); + + if (JERRY_UNLIKELY (builtin_routine_id <= ECMA_ARRAY_PROTOTYPE_CONCAT)) + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_SORT) + { + ret_value = ecma_builtin_array_prototype_object_sort (this_arg, arguments_list_p[0], obj_p); + } + else if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_CONCAT) + { + ret_value = ecma_builtin_array_prototype_object_concat (arguments_list_p, arguments_number, obj_p); + } + + ecma_deref_object (obj_p); + return ret_value; + } + + if (JERRY_UNLIKELY (builtin_routine_id >= ECMA_ARRAY_PROTOTYPE_ENTRIES + && builtin_routine_id <= ECMA_ARRAY_PROTOTYPE_KEYS)) + { + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_ENTRIES) + { + ret_value = ecma_op_create_array_iterator (obj_p, ECMA_ITERATOR_ENTRIES); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_KEYS); + ret_value = ecma_op_create_array_iterator (obj_p, ECMA_ITERATOR_KEYS); + } + + ecma_deref_object (obj_p); + return ret_value; + } + + ecma_length_t length; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (obj_p); + return len_value; + } + + ecma_value_t ret_value; + + switch (builtin_routine_id) + { + case ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING: + { + ret_value = ecma_builtin_array_prototype_object_to_locale_string (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_JOIN: + { + ret_value = ecma_builtin_array_prototype_join (arguments_list_p[0], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_POP: + { + ret_value = ecma_builtin_array_prototype_object_pop (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_PUSH: + { + ret_value = ecma_builtin_array_prototype_object_push (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_REVERSE: + { + ret_value = ecma_builtin_array_prototype_object_reverse (this_arg, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SHIFT: + { + ret_value = ecma_builtin_array_prototype_object_shift (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SLICE: + { + ret_value = ecma_builtin_array_prototype_object_slice (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SPLICE: + { + ret_value = ecma_builtin_array_prototype_object_splice (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_UNSHIFT: + { + ret_value = ecma_builtin_array_prototype_object_unshift (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_AT: + { + ret_value = ecma_builtin_array_prototype_object_at (arguments_list_p[0], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_INDEX_OF: + { + ret_value = ecma_builtin_array_prototype_object_index_of (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF: + { + ret_value = ecma_builtin_array_prototype_object_last_index_of (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_EVERY: + case ECMA_ARRAY_PROTOTYPE_SOME: + case ECMA_ARRAY_PROTOTYPE_FOR_EACH: + { + ret_value = ecma_builtin_array_apply (arguments_list_p[0], + arguments_list_p[1], + (array_routine_mode) (builtin_routine_id - (uint8_t) ECMA_ARRAY_PROTOTYPE_EVERY), + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_MAP: + { + ret_value = ecma_builtin_array_prototype_object_map (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_REDUCE: + case ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT: + { + ret_value = ecma_builtin_array_reduce_from (arguments_list_p, + arguments_number, + builtin_routine_id == ECMA_ARRAY_PROTOTYPE_REDUCE, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_COPY_WITHIN: + { + ret_value = ecma_builtin_array_prototype_object_copy_within (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FIND: + case ECMA_ARRAY_PROTOTYPE_FIND_INDEX: + { + ret_value = ecma_builtin_array_prototype_object_find (arguments_list_p[0], + arguments_list_p[1], + builtin_routine_id == ECMA_ARRAY_PROTOTYPE_FIND, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FILL: + { + ret_value = ecma_builtin_array_prototype_fill (arguments_list_p[0], + arguments_list_p[1], + arguments_list_p[2], + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_INCLUDES: + { + ret_value = ecma_builtin_array_prototype_includes (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FLAT: + { + ret_value = ecma_builtin_array_prototype_object_flat (arguments_list_p, arguments_number, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_FLATMAP: + { + ret_value = + ecma_builtin_array_prototype_object_flat_map (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_FILTER); + + ret_value = ecma_builtin_array_prototype_object_filter (arguments_list_p[0], arguments_list_p[1], obj_p, length); + break; + } + } + + ecma_free_value (len_value); + ecma_deref_object (obj_p); + + return ret_value; +} /* ecma_builtin_array_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h new file mode 100644 index 00000000..19110f78 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h @@ -0,0 +1,85 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Array.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ARRAY + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.4.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 22.1.3.31 */ +OBJECT_VALUE (LIT_GLOBAL_SYMBOL_UNSCOPABLES, + ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Number properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.4.4 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_CONCAT, ECMA_ARRAY_PROTOTYPE_CONCAT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_JOIN, ECMA_ARRAY_PROTOTYPE_JOIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_POP, ECMA_ARRAY_PROTOTYPE_POP, 0, 0) +ROUTINE (LIT_MAGIC_STRING_PUSH, ECMA_ARRAY_PROTOTYPE_PUSH, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_REVERSE, ECMA_ARRAY_PROTOTYPE_REVERSE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SHIFT, ECMA_ARRAY_PROTOTYPE_SHIFT, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_ARRAY_PROTOTYPE_SLICE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SORT, ECMA_ARRAY_PROTOTYPE_SORT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_AT, ECMA_ARRAY_PROTOTYPE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SPLICE, ECMA_ARRAY_PROTOTYPE_SPLICE, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_UNSHIFT, ECMA_ARRAY_PROTOTYPE_UNSHIFT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_INDEX_OF, 2, 1) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF, NON_FIXED, 1) +/* Note these 3 routines must be in this order */ +ROUTINE (LIT_MAGIC_STRING_EVERY, ECMA_ARRAY_PROTOTYPE_EVERY, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SOME, ECMA_ARRAY_PROTOTYPE_SOME, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_ARRAY_PROTOTYPE_FOR_EACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_MAP, ECMA_ARRAY_PROTOTYPE_MAP, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FILTER, ECMA_ARRAY_PROTOTYPE_FILTER, 2, 1) +/* Note these 2 routines must be in this order */ +ROUTINE (LIT_MAGIC_STRING_REDUCE, ECMA_ARRAY_PROTOTYPE_REDUCE, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_ARRAY_PROTOTYPE_FIND, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_ARRAY_PROTOTYPE_FIND_INDEX, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FILL, ECMA_ARRAY_PROTOTYPE_FILL, 3, 1) +ROUTINE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_ARRAY_PROTOTYPE_COPY_WITHIN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_ARRAY_PROTOTYPE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_ARRAY_PROTOTYPE_KEYS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_ARRAY_PROTOTYPE_INCLUDES, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_FLAT, ECMA_ARRAY_PROTOTYPE_FLAT, 1, 0) +ROUTINE (LIT_MAGIC_STRING_FLATMAP, ECMA_ARRAY_PROTOTYPE_FLATMAP, 2, 1) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_STRING_UL, LIT_MAGIC_STRING_TO_STRING_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp new file mode 100644 index 00000000..0d88411f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.cpp @@ -0,0 +1,569 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ARRAY_ROUTINE_START = 0, + ECMA_ARRAY_ROUTINE_IS_ARRAY, + ECMA_ARRAY_ROUTINE_FROM, + ECMA_ARRAY_ROUTINE_OF, + ECMA_ARRAY_ROUTINE_SPECIES_GET +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array.inc.h" +#define BUILTIN_UNDERSCORED_ID array +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup array ECMA Array object built-in + * @{ + */ + +/** + * The Array object's 'from' routine + * + * See also: + * ECMA-262 v6, 22.1.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + /* 1. */ + ecma_value_t constructor = this_arg; + ecma_value_t call_this_arg = ECMA_VALUE_UNDEFINED; + ecma_value_t items = arguments_list_p[0]; + ecma_value_t mapfn = (arguments_list_len > 1) ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED; + ecma_length_t k = 0; + ecma_value_t set_status; + + /* 2. */ + ecma_object_t *mapfn_obj_p = NULL; + + /* 3. */ + if (!ecma_is_value_undefined (mapfn)) + { + /* 3.a */ + if (!ecma_op_is_callable (mapfn)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + /* 3.b */ + if (arguments_list_len > 2) + { + call_this_arg = arguments_list_p[2]; + } + + /* 3.c */ + mapfn_obj_p = ecma_get_object_from_value (mapfn); + } + + /* 4. */ + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (items, LIT_GLOBAL_SYMBOL_ITERATOR); + + /* 5. */ + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + return using_iterator; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 6. */ + if (!ecma_is_value_undefined (using_iterator)) + { + ecma_object_t *array_obj_p; + + /* 6.a */ + if (ecma_is_constructor (constructor)) + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + + ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, NULL, 0); + + if (ecma_is_value_undefined (array) || ecma_is_value_null (array)) + { + ecma_free_value (using_iterator); + return ecma_raise_type_error (ECMA_ERR_CANNOT_CONVERT_TO_OBJECT); + } + + /* 6.c */ + if (ECMA_IS_VALUE_ERROR (array)) + { + ecma_free_value (using_iterator); + return array; + } + + array_obj_p = ecma_get_object_from_value (array); + } + else + { + /* 6.b */ + array_obj_p = ecma_op_new_array_object (0); + } + + /* 6.d */ + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (items, using_iterator, &next_method); + ecma_free_value (using_iterator); + + /* 6.e */ + if (ECMA_IS_VALUE_ERROR (iterator)) + { + ecma_deref_object (array_obj_p); + return iterator; + } + + /* 6.f */ + uint32_t k = 0; + + /* 6.g */ + while (true) + { + /* 6.g.ii */ + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + /* 6.g.iii */ + if (ECMA_IS_VALUE_ERROR (next)) + { + goto iterator_cleanup; + } + + /* 6.g.iii */ + if (ecma_is_value_false (next)) + { + /* 6.g.iv.1 */ + ecma_value_t len_value = ecma_make_uint32_value (k); + ecma_value_t set_status = + ecma_op_object_put (array_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len_value, true); + ecma_free_value (len_value); + + /* 6.g.iv.2 */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + goto iterator_cleanup; + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + /* 6.g.iv.3 */ + return ecma_make_object_value (array_obj_p); + } + + /* 6.g.v */ + ecma_value_t next_value = ecma_op_iterator_value (next); + + ecma_free_value (next); + + /* 6.g.vi */ + if (ECMA_IS_VALUE_ERROR (next_value)) + { + goto iterator_cleanup; + } + + ecma_value_t mapped_value; + /* 6.g.vii */ + if (mapfn_obj_p != NULL) + { + /* 6.g.vii.1 */ + ecma_value_t args_p[2] = { next_value, ecma_make_uint32_value (k) }; + /* 6.g.vii.3 */ + mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2); + ecma_free_value (args_p[1]); + ecma_free_value (next_value); + + /* 6.g.vii.2 */ + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + ecma_op_iterator_close (iterator); + goto iterator_cleanup; + } + } + else + { + /* 6.g.viii */ + mapped_value = next_value; + } + + /* 6.g.ix */ + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + ecma_value_t set_status = ecma_builtin_helper_def_prop_by_index (array_obj_p, k, mapped_value, flags); + + ecma_free_value (mapped_value); + + /* 6.g.x */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + ecma_op_iterator_close (iterator); + goto iterator_cleanup; + } + + /* 6.g.xi */ + k++; + } + +iterator_cleanup: + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_deref_object (array_obj_p); + + return ret_value; + } + + /* 8. */ + ecma_value_t array_like = ecma_op_to_object (items); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (array_like)) + { + return array_like; + } + + ecma_object_t *array_like_obj_p = ecma_get_object_from_value (array_like); + + /* 10. */ + ecma_length_t len; + ecma_value_t len_value = ecma_op_object_get_length (array_like_obj_p, &len); + + /* 11. */ + if (ECMA_IS_VALUE_ERROR (len_value)) + { + goto cleanup; + } + + /* 12. */ + ecma_object_t *array_obj_p; + + /* 12.a */ + if (ecma_is_constructor (constructor)) + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + + len_value = ecma_make_length_value (len); + ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &len_value, 1); + ecma_free_value (len_value); + + if (ecma_is_value_undefined (array) || ecma_is_value_null (array)) + { + ecma_raise_type_error (ECMA_ERR_CANNOT_CONVERT_TO_OBJECT); + goto cleanup; + } + + /* 14. */ + if (ECMA_IS_VALUE_ERROR (array)) + { + goto cleanup; + } + + array_obj_p = ecma_get_object_from_value (array); + } + else + { + /* 13.a */ + array_obj_p = ecma_op_new_array_object_from_length (len); + + if (JERRY_UNLIKELY (array_obj_p == NULL)) + { + goto cleanup; + } + } + + /* 15. */ + k = 0; + + /* 16. */ + while (k < len) + { + /* 16.b */ + ecma_value_t k_value = ecma_op_object_get_by_index (array_like_obj_p, k); + + /* 16.c */ + if (ECMA_IS_VALUE_ERROR (k_value)) + { + goto construct_cleanup; + } + + ecma_value_t mapped_value; + /* 16.d */ + if (mapfn_obj_p != NULL) + { + /* 16.d.i */ + ecma_value_t args_p[2] = { k_value, ecma_make_length_value (k) }; + mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2); + ecma_free_value (args_p[1]); + ecma_free_value (k_value); + + /* 16.d.ii */ + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + goto construct_cleanup; + } + } + else + { + /* 16.e */ + mapped_value = k_value; + } + + /* 16.f */ + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + ecma_value_t set_status = ecma_builtin_helper_def_prop_by_index (array_obj_p, k, mapped_value, flags); + + ecma_free_value (mapped_value); + + /* 16.g */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + goto construct_cleanup; + } + + /* 16.h */ + k++; + } + + /* 17. */ + len_value = ecma_make_length_value (k); + set_status = ecma_op_object_put (array_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len_value, true); + ecma_free_value (len_value); + + /* 18. */ + if (ECMA_IS_VALUE_ERROR (set_status)) + { + goto construct_cleanup; + } + + /* 19. */ + ecma_deref_object (array_like_obj_p); + return ecma_make_object_value (array_obj_p); + +construct_cleanup: + ecma_deref_object (array_obj_p); +cleanup: + ecma_deref_object (array_like_obj_p); + return ret_value; +} /* ecma_builtin_array_object_from */ + +/** + * The Array object's 'of' routine + * + * See also: + * ECMA-262 v6, 22.1.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_array_object_of (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (!ecma_is_constructor (this_arg)) + { + return ecma_op_new_array_object_from_buffer (arguments_list_p, arguments_list_len); + } + + ecma_value_t len = ecma_make_uint32_value (arguments_list_len); + + ecma_value_t ret_val = + ecma_op_function_construct (ecma_get_object_from_value (this_arg), ecma_get_object_from_value (this_arg), &len, 1); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + ecma_free_value (len); + return ret_val; + } + + uint32_t k = 0; + ecma_object_t *obj_p = ecma_get_object_from_value (ret_val); + const uint32_t prop_status_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + while (k < arguments_list_len) + { + ecma_value_t define_status = + ecma_builtin_helper_def_prop_by_index (obj_p, k, arguments_list_p[k], prop_status_flags); + + if (ECMA_IS_VALUE_ERROR (define_status)) + { + ecma_free_value (len); + ecma_deref_object (obj_p); + return define_status; + } + + k++; + } + + ret_val = ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len, true); + + ecma_free_value (len); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + ecma_deref_object (obj_p); + return ret_val; + } + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_array_object_of */ + +/** + * Handle calling [[Call]] of built-in Array object + * + * @return ECMA_VALUE_ERROR - if the array construction fails + * constructed array object - otherwise + */ +ecma_value_t +ecma_builtin_array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len != 1 || !ecma_is_value_number (arguments_list_p[0])) + { + return ecma_op_new_array_object_from_buffer (arguments_list_p, arguments_list_len); + } + + ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]); + uint32_t num_uint32 = ecma_number_to_uint32 (num); + + if (num != ((ecma_number_t) num_uint32)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + return ecma_make_object_value (ecma_op_new_array_object (num_uint32)); +} /* ecma_builtin_array_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Array object + * + * @return ECMA_VALUE_ERROR - if the array construction fails + * constructed array object - otherwise + */ +ecma_value_t +ecma_builtin_array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_array_dispatch_call (arguments_list_p, arguments_list_len); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (proto_p); + return result; + } + + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + ecma_deref_object (proto_p); + return result; +} /* ecma_builtin_array_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_array_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { + case ECMA_ARRAY_ROUTINE_IS_ARRAY: + { + JERRY_UNUSED (this_arg); + + return ecma_is_value_array (arguments_list_p[0]); + } + case ECMA_ARRAY_ROUTINE_FROM: + { + return ecma_builtin_array_object_from (this_arg, arguments_list_p, arguments_number); + } + case ECMA_ARRAY_ROUTINE_OF: + { + return ecma_builtin_array_object_of (this_arg, arguments_list_p, arguments_number); + } + case ECMA_ARRAY_ROUTINE_SPECIES_GET: + { + return ecma_copy_value (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_array_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h new file mode 100644 index 00000000..bf43da90 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h @@ -0,0 +1,47 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Array description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ARRAY + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.4.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ARRAY_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ARRAY_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_IS_ARRAY_UL, ECMA_ARRAY_ROUTINE_IS_ARRAY, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FROM, ECMA_ARRAY_ROUTINE_FROM, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_OF, ECMA_ARRAY_ROUTINE_OF, NON_FIXED, 0) + +/* ECMA-262 v6, 22.1.2.5 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ECMA_ARRAY_ROUTINE_SPECIES_GET, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* !(JERRY_BUILTIN_ARRAY) */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.cpp new file mode 100644 index 00000000..3e47e068 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.cpp @@ -0,0 +1,116 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-arraybuffer-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID arraybuffer_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup arraybufferprototype ECMA ArrayBuffer.prototype object built-in + * @{ + */ + +/** + * The ArrayBuffer.prototype.bytelength accessor + * + * See also: + * ES2015, 24.1.4.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_arraybuffer_prototype_bytelength_getter (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)) + { + if (ecma_arraybuffer_is_detached (object_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + uint32_t len = ecma_arraybuffer_get_length (object_p); + + return ecma_make_uint32_value (len); + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT); +} /* ecma_builtin_arraybuffer_prototype_bytelength_getter */ + +/** + * The ArrayBuffer.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v11, 24.1.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number) /**< number of arguments */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + /* 2. */ + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ARRAY_BUFFER_OBJECT); + } + + return ecma_builtin_arraybuffer_slice (this_arg, argument_list_p, arguments_number); +} /* ecma_builtin_arraybuffer_prototype_object_slice */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h new file mode 100644 index 00000000..80463446 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ArrayBuffer.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ARRAYBUFFER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Readonly accessor properties */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ecma_builtin_arraybuffer_prototype_bytelength_getter, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 24.1.4.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_arraybuffer_prototype_object_slice, NON_FIXED, 2) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.cpp new file mode 100644 index 00000000..cb26f0a9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.cpp @@ -0,0 +1,114 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtins.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-arraybuffer.inc.h" +#define BUILTIN_UNDERSCORED_ID arraybuffer +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup arraybuffer ECMA ArrayBuffer object built-in + * @{ + */ + +/** + * The ArrayBuffer object's 'isView' routine + * + * See also: + * ES2015 24.1.3.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_arraybuffer_object_is_view (ecma_value_t this_arg, /**< 'this' argument */ + ecma_value_t arg) /**< argument 1 */ +{ + JERRY_UNUSED (this_arg); + + return ecma_make_boolean_value (ecma_is_typedarray (arg) || ecma_is_dataview (arg)); +} /* ecma_builtin_arraybuffer_object_is_view */ + +/** + * Handle calling [[Call]] of built-in ArrayBuffer object + * + * ES2015 24.1.2 ArrayBuffer is not intended to be called as + * a function and will throw an exception when called in + * that manner. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_arraybuffer_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_ARRAYBUFFER_REQUIRES_NEW); +} /* ecma_builtin_arraybuffer_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in ArrayBuffer object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_arraybuffer_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_arraybuffer_object (arguments_list_p, arguments_list_len); +} /* ecma_builtin_arraybuffer_dispatch_construct */ + +/** + * 24.1.3.3 get ArrayBuffer [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_arraybuffer_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_arraybuffer_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h new file mode 100644 index 00000000..6fe1a936 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h @@ -0,0 +1,47 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ArrayBuffer built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +/* ES2015 24.1.3.1 */ +ROUTINE (LIT_MAGIC_STRING_IS_VIEW_UL, ecma_builtin_arraybuffer_object_is_view, 1, 1) + +/* ES2015 24.1.3.3 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_arraybuffer_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.cpp new file mode 100644 index 00000000..8f1b10e0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.cpp @@ -0,0 +1,355 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerryscript-types.h" + +#include "ecma-builtin-handlers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "jrt.h" +#include "lit-magic-strings.h" +#include "lit-strings.h" +#include "opcodes.h" +#include "vm-defines.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_START = 0, /**< buitlin routine start id */ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_NEXT, /**< 'next' routine v11, 25.1.4.2.1 */ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_RETURN, /**< 'return' routine v11, 25.1.4.2.2 */ + ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_THROW /**< 'throw' routine v11, 25.1.4.2.3 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-from-sync-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_from_sync_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncfromsynciteratorprototype ECMA %AsyncFromSyncIteratorPrototype% object built-in + * @{ + */ + +/** + * AsyncFromSyncIteratorContinuation operation + * + * See also: + * ECMAScript v11, 25.1.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_async_from_sync_iterator_prototype_continuation (ecma_value_t result, /**< routine's 'result' argument */ + ecma_object_t *capability_obj_p) /**< promise capability */ +{ + /* 1. */ + ecma_value_t done = ecma_op_iterator_complete (result); + + /* 2. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&done, capability_obj_p))) + { + return done; + } + + uint16_t done_flag = ecma_is_value_false (done) ? 0 : (1 << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT); + ecma_free_value (done); + + /* 3. */ + ecma_value_t value = ecma_op_iterator_value (result); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&value, capability_obj_p))) + { + return value; + } + + /* 5. */ + ecma_value_t builtin_promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + ecma_value_t value_wrapper = ecma_promise_reject_or_resolve (builtin_promise, value, true); + ecma_free_value (value); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&value_wrapper, capability_obj_p))) + { + return value_wrapper; + } + + /* 8 - 9. */ + ecma_object_t *on_fullfilled = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP, + sizeof (ecma_extended_object_t)); + ((ecma_extended_object_t *) on_fullfilled)->u.built_in.u2.routine_flags = (uint8_t) done_flag; + + /* 10. */ + ecma_value_t then_result = ecma_promise_perform_then (value_wrapper, + ecma_make_object_value (on_fullfilled), + ECMA_VALUE_UNDEFINED, + capability_obj_p); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (then_result)); + ecma_deref_object (on_fullfilled); + ecma_free_value (value_wrapper); + + /* 11. */ + return then_result; +} /* ecma_op_async_from_sync_iterator_prototype_continuation */ + +/** + * The %AsyncFromSyncIteratorPrototype% object's 'next' routine + * + * See also: + * ECMAScript v11, 25.1.4.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_async_from_sync_iterator_prototype_next (ecma_async_from_sync_iterator_object_t *iter_p, /**< iterator + * record*/ + ecma_object_t *capability_p, /**< promise capability */ + ecma_value_t value) /**< routine's 'value' argument */ +{ + /* 5. */ + ecma_value_t next_result = + ecma_op_iterator_next (iter_p->header.u.cls.u3.sync_iterator, iter_p->sync_next_method, value); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&next_result, capability_p))) + { + return next_result; + } + + /* 7. */ + ecma_value_t result = ecma_op_async_from_sync_iterator_prototype_continuation (next_result, capability_p); + ecma_free_value (next_result); + + return result; +} /* ecma_builtin_async_from_sync_iterator_prototype_next */ + +/** + * The %AsyncFromSyncIteratorPrototype% object's 'return' and 'throw' routines + * + * See also: + * ECMAScript v11, 25.1.4.2.2 + * ECMAScript v11, 25.1.4.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_async_from_sync_iterator_prototype_do (ecma_async_from_sync_iterator_object_t *iter_p, /**< iterator + * record*/ + ecma_object_t *capability_obj_p, /**< promise capability */ + ecma_value_t value, /**< routine's 'value' argument */ + lit_magic_string_id_t method_id) /**< method id */ +{ + /* 5. */ + ecma_value_t sync_iterator = iter_p->header.u.cls.u3.sync_iterator; + ecma_value_t method = ecma_op_get_method_by_magic_id (sync_iterator, method_id); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&method, capability_obj_p))) + { + return method; + } + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t call_arg; + uint32_t arg_size; + + if (ecma_is_value_empty (value)) + { + arg_size = 0; + call_arg = ECMA_VALUE_UNDEFINED; + } + else + { + arg_size = 1; + call_arg = value; + } + + /* 7. */ + if (ecma_is_value_undefined (method)) + { + ecma_value_t func_obj; + + if (method_id == LIT_MAGIC_STRING_RETURN) + { + /* 7.a. */ + call_arg = ecma_create_iter_result_object (call_arg, ECMA_VALUE_TRUE); + arg_size = 1; + func_obj = capability_p->resolve; + } + else + { + func_obj = capability_p->reject; + } + + /* 7.b. */ + ecma_value_t resolve = + ecma_op_function_call (ecma_get_object_from_value (func_obj), ECMA_VALUE_UNDEFINED, &call_arg, arg_size); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (resolve)); + ecma_free_value (resolve); + + if (method_id == LIT_MAGIC_STRING_RETURN) + { + ecma_free_value (call_arg); + } + + /* 7.c. */ + return ecma_copy_value (capability_p->header.u.cls.u3.promise); + } + + /* 8. */ + ecma_value_t call_result = ecma_op_function_validated_call (method, sync_iterator, &call_arg, arg_size); + ecma_free_value (method); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&call_result, capability_obj_p))) + { + return call_result; + } + + /* 10. */ + if (!ecma_is_value_object (call_result)) + { + ecma_free_value (call_result); + +#if JERRY_ERROR_MESSAGES + const lit_utf8_byte_t *msg_p = (lit_utf8_byte_t *) ecma_get_error_msg (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + lit_utf8_size_t msg_size = ecma_get_error_size (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + ecma_string_t *error_msg_p = ecma_new_ecma_string_from_ascii (msg_p, msg_size); +#else /* !JERRY_ERROR_MESSAGES */ + ecma_string_t *error_msg_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + + ecma_object_t *type_error_obj_p = ecma_new_standard_error (JERRY_ERROR_TYPE, error_msg_p); + +#if JERRY_ERROR_MESSAGES + ecma_deref_ecma_string (error_msg_p); +#endif /* JERRY_ERROR_MESSAGES */ + + ecma_value_t type_error = ecma_make_object_value (type_error_obj_p); + + /* 10.a. */ + ecma_value_t reject = + ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &type_error, 1); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (reject)); + ecma_deref_object (type_error_obj_p); + ecma_free_value (reject); + + /* 10.b. */ + return ecma_copy_value (capability_p->header.u.cls.u3.promise); + } + + ecma_value_t result = ecma_op_async_from_sync_iterator_prototype_continuation (call_result, capability_obj_p); + ecma_free_value (call_result); + + return result; +} /* ecma_builtin_async_from_sync_iterator_prototype_do */ + +/** + * Dispatcher of the %AsyncFromSyncIteratorPrototype% built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_async_from_sync_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of + * arguments + * passed to + * routine */ + uint32_t arguments_number) /**< length of + * arguments' list */ +{ + JERRY_UNUSED (arguments_number); + JERRY_ASSERT (ecma_is_value_object (this_arg)); + + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + + JERRY_ASSERT (ecma_object_class_is (this_obj_p, ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR)); + + ecma_async_from_sync_iterator_object_t *iter_p = (ecma_async_from_sync_iterator_object_t *) this_obj_p; + + ecma_value_t builtin_promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + ecma_object_t *capability_p = ecma_promise_new_capability (builtin_promise, ECMA_VALUE_UNDEFINED); + JERRY_ASSERT (capability_p != NULL); + + ecma_value_t result; + ecma_value_t arg = (arguments_number == 0 ? ECMA_VALUE_EMPTY : arguments_list_p[0]); + + switch (builtin_routine_id) + { + case ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_NEXT: + { + result = ecma_builtin_async_from_sync_iterator_prototype_next (iter_p, capability_p, arg); + break; + } + case ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_RETURN: + { + result = ecma_builtin_async_from_sync_iterator_prototype_do (iter_p, capability_p, arg, LIT_MAGIC_STRING_RETURN); + break; + } + case ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_THROW: + { + result = ecma_builtin_async_from_sync_iterator_prototype_do (iter_p, capability_p, arg, LIT_MAGIC_STRING_THROW); + break; + } + default: + { + JERRY_UNREACHABLE (); + break; + } + } + + ecma_deref_object (capability_p); + + return result; +} /* ecma_builtin_async_from_sync_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.inc.h new file mode 100644 index 00000000..7c5e9c39 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncFromSyncIteratorPrototype% built-in description (AsyncFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_NEXT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RETURN, ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_RETURN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_THROW, ECMA_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_ROUTINE_THROW, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.cpp new file mode 100644 index 00000000..6be0c162 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.cpp @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-function-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_function_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncfunctionprototype ECMA AsyncFunction.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h new file mode 100644 index 00000000..e4388d3c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncFunctionPrototype% built-in description (AsyncFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v11, 25.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ASYNC_FUNCTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 25.7.3.2 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.cpp new file mode 100644 index 00000000..de1a7dbc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.cpp @@ -0,0 +1,68 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" +#include "ecma-function-object.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-function.inc.h" +#define BUILTIN_UNDERSCORED_ID async_function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncfunction ECMA AsyncFunction object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in AsyncFunction object + * + * @return constructed async function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_ASYNC_FUNCTION); +} /* ecma_builtin_async_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in AsyncFunction object + * + * @return constructed async function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_async_function_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_async_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.inc.h new file mode 100644 index 00000000..0fe50ae2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-function.inc.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncFunction% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v11, 25.7.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 25.7.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v10, 25.7.2.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v11, 25.7.3.2 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.cpp new file mode 100644 index 00000000..18ad25ef --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.cpp @@ -0,0 +1,70 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" +#include "ecma-function-object.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-generator-function.inc.h" +#define BUILTIN_UNDERSCORED_ID async_generator_function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncgeneratorfunction ECMA AsyncGeneratorFunction object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in AsyncGeneratorFunction object + * + * @return constructed async generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_generator_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_dynamic_function (arguments_list_p, + arguments_list_len, + (ecma_parse_opts_t)(((unsigned int) ECMA_PARSE_GENERATOR_FUNCTION) | ((unsigned int) ECMA_PARSE_ASYNC_FUNCTION))); +} /* ecma_builtin_async_generator_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in AsyncGeneratorFunction object + * + * @return constructed async generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_async_generator_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_async_generator_function_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_async_generator_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h new file mode 100644 index 00000000..edc88c71 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncGeneratorFunction% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v10, 25.3.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v10, 25.3.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ASYNC_GENERATOR, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.cpp new file mode 100644 index 00000000..3ea9dea0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.cpp @@ -0,0 +1,147 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-async-generator-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-defines.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT, + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW, + ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_RETURN +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-generator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_generator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncgeneratorprototype ECMA AsyncGenerator.prototype object built-in + * @{ + */ + +/** + * Convert routine type to operation type. + */ +#define ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION(type) \ + ((ecma_async_generator_operation_type_t) ((type) -ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT)) + +JERRY_STATIC_ASSERT ((ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT) == ECMA_ASYNC_GENERATOR_DO_NEXT), + convert_ecma_async_generator_routine_next_to_ecma_async_generator_do_next_failed); + +JERRY_STATIC_ASSERT ((ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW) == ECMA_ASYNC_GENERATOR_DO_THROW), + convert_ecma_async_generator_routine_throw_to_ecma_async_generator_do_throw_failed); + +JERRY_STATIC_ASSERT ((ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_RETURN) == ECMA_ASYNC_GENERATOR_DO_RETURN), + convert_ecma_async_generator_routine_return_to_ecma_async_generator_do_return_failed); + +/** + * Dispatcher of the Generator built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_async_generator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to + * routine */ + uint32_t arguments_number) /**< length of arguments' + * list */ +{ + JERRY_UNUSED (arguments_number); + + vm_executable_object_t *executable_object_p = NULL; + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ASYNC_GENERATOR)) + { + executable_object_p = (vm_executable_object_t *) object_p; + } + } + + if (executable_object_p == NULL) + { + const char *msg_p = ecma_get_error_msg (ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR); + lit_utf8_size_t msg_size = ecma_get_error_size (ECMA_ERR_ARGUMENT_THIS_NOT_ASYNC_GENERATOR); + ecma_string_t *error_msg_p = ecma_new_ecma_string_from_ascii ((const lit_utf8_byte_t *) msg_p, msg_size); + + ecma_object_t *type_error_obj_p = ecma_new_standard_error (JERRY_ERROR_TYPE, error_msg_p); + ecma_deref_ecma_string (error_msg_p); + + ecma_value_t promise = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + ecma_reject_promise (promise, ecma_make_object_value (type_error_obj_p)); + ecma_deref_object (type_error_obj_p); + + return promise; + } + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + ecma_value_t promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW)) + { + return ecma_promise_reject_or_resolve (promise, arguments_list_p[0], false); + } + + ecma_value_t iter_result = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + ecma_value_t result = ecma_promise_reject_or_resolve (promise, iter_result, true); + ecma_free_value (iter_result); + return result; + } + + return ecma_async_generator_enqueue (executable_object_p, + ECMA_ASYNC_GENERATOR_ROUTINE_TO_OPERATION (builtin_routine_id), + arguments_list_p[0]); +} /* ecma_builtin_async_generator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h new file mode 100644 index 00000000..dcad1c62 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * AsyncGenerator.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 25.3.1.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ASYNC_GENERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ASYNC_GENERATOR, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_NEXT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RETURN, ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_RETURN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_THROW, ECMA_ASYNC_GENERATOR_PROTOTYPE_ROUTINE_THROW, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.cpp new file mode 100644 index 00000000..46937420 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.cpp @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-generator.inc.h" +#define BUILTIN_UNDERSCORED_ID async_generator +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup asyncgenerator ECMA AsyncGenerator object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.inc.h new file mode 100644 index 00000000..a856cbbe --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-generator.inc.h @@ -0,0 +1,33 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncGenerator% built-in description (AsyncGeneratorFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v6, 25.3.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ASYNC_GENERATOR_FUNCTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.3 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.cpp new file mode 100644 index 00000000..28579fee --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.cpp @@ -0,0 +1,103 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_OBJECT_ASYNC_ITERATOR, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID async_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %asynciteratorprototype% ECMA %AsyncIteratorPrototype% object built-in + * @{ + */ + +/** + * The %AsyncIteratorPrototype% object's '@@asyncIterator' routine + * + * See also: + * ECMA-262 v10, 25.1.3.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return the given this value + */ +static ecma_value_t +ecma_builtin_async_iterator_prototype_object_async_iterator (ecma_value_t this_val) /**< this argument */ +{ + /* 1. */ + return ecma_copy_value (this_val); +} /* ecma_builtin_async_iterator_prototype_object_async_iterator */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_async_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< + * list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_OBJECT_ASYNC_ITERATOR: + { + return ecma_builtin_async_iterator_prototype_object_async_iterator (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_async_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h new file mode 100644 index 00000000..53d43d00 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %AsyncIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, ECMA_BUILTIN_ASYNC_ITERATOR_PROTOTYPE_OBJECT_ASYNC_ITERATOR, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.cpp new file mode 100644 index 00000000..c7d1847c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.cpp @@ -0,0 +1,260 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-atomics-object.h" +#include "ecma-builtins.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ATOMICS + +#define ECMA_BUILTINS_INTERNAL + +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ATOMICS_ROUTINE_START = 0, /**< Special value, should be ignored */ + ECMA_ATOMICS_ROUTINE_ADD, /**< Atomics add routine */ + ECMA_ATOMICS_ROUTINE_AND, /**< Atomics and routine */ + ECMA_ATOMICS_ROUTINE_COMPAREEXCHANGE, /**< Atomics compare exchange routine */ + ECMA_ATOMICS_ROUTINE_EXCHANGE, /**< Atomics exchange routine */ + ECMA_ATOMICS_ROUTINE_ISLOCKFREE, /**< Atomics is lock free routine */ + ECMA_ATOMICS_ROUTINE_LOAD, /**< Atomics load routine */ + ECMA_ATOMICS_ROUTINE_OR, /**< Atomics or routine */ + ECMA_ATOMICS_ROUTINE_STORE, /**< Atomics store routine */ + ECMA_ATOMICS_ROUTINE_SUB, /**< Atomics sub routine */ + ECMA_ATOMICS_ROUTINE_WAIT, /**< Atomics wait routine */ + ECMA_ATOMICS_ROUTINE_NOTIFY, /**< Atomics notify routine */ + ECMA_ATOMICS_ROUTINE_XOR, /**< Atomics xor routine */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-atomics.inc.h" +#define BUILTIN_UNDERSCORED_ID atomics + +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup atomics ECMA Atomics object built-in + * @{ + */ + +/** + * The Atomics object's 'compareExchange' routine + * + * See also: ES11 24.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_compare_exchange (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t expected_value, /**< expectedValue argument */ + ecma_value_t replacement_value) /**< replacementValue argument*/ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (expected_value); + JERRY_UNUSED (replacement_value); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_compare_exchange */ + +/** + * The Atomics object's 'isLockFree' routine + * + * See also: ES11 24.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_is_lock_free (ecma_value_t size) /**< size argument */ +{ + JERRY_UNUSED (size); + + return ECMA_VALUE_FALSE; +} /* ecma_builtin_atomics_is_lock_free */ + +/** + * The Atomics object's 'store' routine + * + * See also: ES11 24.4.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_store (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t value) /**< value argument */ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (value); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_store */ + +/** + * The Atomics object's 'wait' routine + * + * See also: ES11 24.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_wait (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t value, /**< value argument */ + ecma_value_t timeout) /**< timeout argument */ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (value); + JERRY_UNUSED (timeout); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_wait */ + +/** + * The Atomics object's 'notify' routine + * + * See also: ES11 24.4.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_atomics_notify (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t count) /**< count argument */ +{ + JERRY_UNUSED (typedarray); + JERRY_UNUSED (index); + JERRY_UNUSED (count); + + return ecma_make_uint32_value (0); +} /* ecma_builtin_atomics_notify */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_atomics_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + ecma_value_t arg1 = arguments_list_p[0]; + ecma_value_t arg2 = arguments_list_p[1]; + ecma_value_t arg3 = arguments_list_p[2]; + ecma_value_t arg4 = (arguments_number > 3) ? arguments_list_p[3] : ECMA_VALUE_UNDEFINED; + + ecma_atomics_op_t type; + + switch (builtin_routine_id) + { + case ECMA_ATOMICS_ROUTINE_ADD: + { + type = ECMA_ATOMICS_ADD; + break; + } + case ECMA_ATOMICS_ROUTINE_AND: + { + type = ECMA_ATOMICS_AND; + break; + } + case ECMA_ATOMICS_ROUTINE_COMPAREEXCHANGE: + { + return ecma_builtin_atomics_compare_exchange (arg1, arg2, arg3, arg4); + } + case ECMA_ATOMICS_ROUTINE_EXCHANGE: + { + type = ECMA_ATOMICS_EXCHANGE; + break; + } + case ECMA_ATOMICS_ROUTINE_ISLOCKFREE: + { + return ecma_builtin_atomics_is_lock_free (arg1); + } + case ECMA_ATOMICS_ROUTINE_LOAD: + { + return ecma_atomic_load (arg1, arg2); + } + case ECMA_ATOMICS_ROUTINE_OR: + { + type = ECMA_ATOMICS_OR; + break; + } + case ECMA_ATOMICS_ROUTINE_STORE: + { + return ecma_builtin_atomics_store (arg1, arg2, arg3); + } + case ECMA_ATOMICS_ROUTINE_SUB: + { + type = ECMA_ATOMICS_SUBTRACT; + break; + } + case ECMA_ATOMICS_ROUTINE_WAIT: + { + return ecma_builtin_atomics_wait (arg1, arg2, arg3, arg4); + } + case ECMA_ATOMICS_ROUTINE_NOTIFY: + { + return ecma_builtin_atomics_notify (arg1, arg2, arg3); + } + case ECMA_ATOMICS_ROUTINE_XOR: + { + type = ECMA_ATOMICS_XOR; + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + return ecma_atomic_read_modify_write (arg1, arg2, arg3, type); +} /* ecma_builtin_atomics_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ATOMICS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.inc.h new file mode 100644 index 00000000..a11b4518 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-atomics.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Atomics built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ATOMICS + +/* ECMA-262 v11, 24.4.14 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_ATOMICS_U, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_ADD, ECMA_ATOMICS_ROUTINE_ADD, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_AND, ECMA_ATOMICS_ROUTINE_AND, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_COMPAREEXCHANGE, ECMA_ATOMICS_ROUTINE_COMPAREEXCHANGE, 4, 4) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_EXCHANGE, ECMA_ATOMICS_ROUTINE_EXCHANGE, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_ISLOCKFREE, ECMA_ATOMICS_ROUTINE_ISLOCKFREE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_LOAD, ECMA_ATOMICS_ROUTINE_LOAD, 2, 2) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_OR, ECMA_ATOMICS_ROUTINE_OR, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_STORE, ECMA_ATOMICS_ROUTINE_STORE, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_SUB, ECMA_ATOMICS_ROUTINE_SUB, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_WAIT, ECMA_ATOMICS_ROUTINE_WAIT, 4, 4) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_NOTIFY, ECMA_ATOMICS_ROUTINE_NOTIFY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_ATOMICS_XOR, ECMA_ATOMICS_ROUTINE_XOR, 3, 3) + +#endif /* JERRY_BUILTIN_ATOMICS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.cpp new file mode 100644 index 00000000..4e6ad9bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.cpp @@ -0,0 +1,186 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BIGINT_PROTOTYPE_ROUTINE_START = 0, + ECMA_BIGINT_PROTOTYPE_VALUE_OF, + ECMA_BIGINT_PROTOTYPE_TO_STRING, + ECMA_BIGINT_PROTOTYPE_TO_LOCALE_STRING, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint ECMA BigInt object built-in + * @{ + */ + +/** + * The BigInt.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v11, 20.2.3.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_bigint_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_bigint (this_arg)) + { + return ecma_copy_value (this_arg); + } + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_BIGINT)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_bigint (ext_object_p->u.cls.u3.value)); + + return ecma_copy_value (ext_object_p->u.cls.u3.value); + } + } + + return ecma_raise_type_error (ECMA_ERR_BIGINT_VALUE_EXCPECTED); +} /* ecma_builtin_bigint_prototype_object_value_of */ + +/** + * The BigInt.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v11, 20.2.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_bigint_prototype_object_to_string (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + uint32_t radix = 10; + + if (arguments_list_len > 0 && !ecma_is_value_undefined (arguments_list_p[0])) + { + ecma_number_t arg_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arguments_list_p[0], &arg_num))) + { + return ECMA_VALUE_ERROR; + } + + if (arg_num < 2 || arg_num > 36) + { + return ecma_raise_range_error (ECMA_ERR_RADIX_IS_OUT_OF_RANGE); + } + + radix = (uint32_t) arg_num; + } + + ecma_string_t *string_p = ecma_bigint_to_string (this_arg, radix); + + if (string_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_string_value (string_p); +} /* ecma_builtin_bigint_prototype_object_to_string */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_bigint_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_value_t this_value = ecma_builtin_bigint_prototype_object_value_of (this_arg); + ecma_value_t ret_val; + + if (ECMA_IS_VALUE_ERROR (this_value)) + { + return this_value; + } + + switch (builtin_routine_id) + { + case ECMA_BIGINT_PROTOTYPE_VALUE_OF: + { + ret_val = this_value; + break; + } + case ECMA_BIGINT_PROTOTYPE_TO_STRING: + { + ret_val = ecma_builtin_bigint_prototype_object_to_string (this_value, arguments_list_p, arguments_number); + ecma_free_value (this_value); + break; + } + case ECMA_BIGINT_PROTOTYPE_TO_LOCALE_STRING: + { + ret_val = ecma_builtin_bigint_prototype_object_to_string (this_value, 0, 0); + ecma_free_value (this_value); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + return ret_val; +} /* ecma_builtin_bigint_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h new file mode 100644 index 00000000..1dc916b0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BIGINT + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v11, 20.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_BIGINT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v11, 20.2.3.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_BIGINT_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_BIGINT_PROTOTYPE_TO_STRING, NON_FIXED, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_BIGINT_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_BIGINT_PROTOTYPE_TO_LOCALE_STRING, 0, 0) + +#endif /* JERRY_BUILTIN_BIGINT */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.cpp new file mode 100644 index 00000000..b349db16 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.cpp @@ -0,0 +1,80 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint ECMA BigInt object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in BigInt object + * + * See also: + * ECMA-262 v11, 20.2.1.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t value = (arguments_list_len == 0) ? ECMA_VALUE_UNDEFINED : arguments_list_p[0]; + return ecma_bigint_to_bigint (value, true); +} /* ecma_builtin_bigint_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in BigInt object + * + * See also: + * ECMA-262 v11, 20.2.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_BIGINT_FUNCTION_NOT_CONSTRUCTOR); +} /* ecma_builtin_bigint_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h new file mode 100644 index 00000000..d8b216ab --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BIGINT + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v11, 20.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 20.2.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_BIGINT_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v11, 20.2.2.3 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_BIGINT_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_BIGINT */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp new file mode 100644 index 00000000..0d71a067 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.cpp @@ -0,0 +1,140 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_BOOLEAN + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BOOLEAN_PROTOTYPE_ROUTINE_START = 0, + ECMA_BOOLEAN_PROTOTYPE_ROUTINE_TO_STRING, + ECMA_BOOLEAN_PROTOTYPE_ROUTINE_VALUE_OF +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-boolean-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID boolean_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup booleanprototype ECMA Boolean.prototype object built-in + * @{ + */ + +/** + * The Boolean.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v5, 15.6.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_boolean_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_boolean (this_arg)) + { + return this_arg; + } + else if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_BOOLEAN)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_boolean (ext_object_p->u.cls.u3.value)); + + return ext_object_p->u.cls.u3.value; + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_BOOLEAN_OBJECT); +} /* ecma_builtin_boolean_prototype_object_value_of */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_boolean_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_number, arguments_list_p); + + ecma_value_t value_of_ret = ecma_builtin_boolean_prototype_object_value_of (this_arg); + if (builtin_routine_id == ECMA_BOOLEAN_PROTOTYPE_ROUTINE_VALUE_OF) + { + return value_of_ret; + } + + JERRY_ASSERT (builtin_routine_id == ECMA_BOOLEAN_PROTOTYPE_ROUTINE_TO_STRING); + + if (ECMA_IS_VALUE_ERROR (value_of_ret)) + { + return value_of_ret; + } + + if (ecma_is_value_true (value_of_ret)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_TRUE); + } + + JERRY_ASSERT (ecma_is_value_false (value_of_ret)); + + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FALSE); +} /* ecma_builtin_boolean_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BOOLEAN */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h new file mode 100644 index 00000000..82ef75f9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Boolean.prototype description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BOOLEAN + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.6.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_BOOLEAN, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_BOOLEAN_PROTOTYPE_ROUTINE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_BOOLEAN_PROTOTYPE_ROUTINE_VALUE_OF, 0, 0) + +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.cpp new file mode 100644 index 00000000..603d6104 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.cpp @@ -0,0 +1,99 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-boolean-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_BOOLEAN + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-boolean.inc.h" +#define BUILTIN_UNDERSCORED_ID boolean +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup boolean ECMA Boolean object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Boolean object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_boolean_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t arg_value; + + if (arguments_list_len == 0) + { + arg_value = ECMA_VALUE_UNDEFINED; + } + else + { + arg_value = arguments_list_p[0]; + } + + return ecma_make_boolean_value (ecma_op_to_boolean (arg_value)); +} /* ecma_builtin_boolean_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Boolean object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_boolean_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0) + { + return ecma_op_create_boolean_object (ECMA_VALUE_FALSE); + } + else + { + return ecma_op_create_boolean_object (arguments_list_p[0]); + } +} /* ecma_builtin_boolean_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BOOLEAN */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h new file mode 100644 index 00000000..36f68455 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Boolean description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_BOOLEAN + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.6.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_BOOLEAN_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.cpp new file mode 100644 index 00000000..6cb9ba3a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.cpp @@ -0,0 +1,238 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" + +#if JERRY_BUILTIN_DATAVIEW + +#if !JERRY_BUILTIN_TYPEDARRAY +#error "DataView builtin requires ES2015 TypedArray builtin" +#endif /* !JERRY_BUILTIN_TYPEDARRAY */ + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_DATAVIEW_PROTOTYPE_ROUTINE_START = 0, + ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER, + ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER, + ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER, + ECMA_DATAVIEW_PROTOTYPE_GET_INT8, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT8, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT8_CLAMPED, /* unused value */ + ECMA_DATAVIEW_PROTOTYPE_GET_INT16, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT16, + ECMA_DATAVIEW_PROTOTYPE_GET_INT32, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT32, + ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32, +#if JERRY_NUMBER_TYPE_FLOAT64 + ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64, +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ECMA_DATAVIEW_PROTOTYPE_GET_BIGINT64, + ECMA_DATAVIEW_PROTOTYPE_GET_BIGUINT64, +#endif /* JERRY_BUILTIN_BIGINT */ + ECMA_DATAVIEW_PROTOTYPE_SET_INT8, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT8, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT8_CLAMPED, /* unused value */ + ECMA_DATAVIEW_PROTOTYPE_SET_INT16, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT16, + ECMA_DATAVIEW_PROTOTYPE_SET_INT32, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT32, + ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32, +#if JERRY_NUMBER_TYPE_FLOAT64 + ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64, +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ECMA_DATAVIEW_PROTOTYPE_SET_BIGINT64, + ECMA_DATAVIEW_PROTOTYPE_SET_BIGUINT64, +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-dataview-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID dataview_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dataviewprototype ECMA DataView.prototype object built-in + * @{ + */ + +/** + * The DataView.prototype object's {buffer, byteOffset, byteLength} getters + * + * See also: + * ECMA-262 v6, 24.2.4.1 + * ECMA-262 v6, 24.2.4.2 + * ECMA-262 v6, 24.2.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_dataview_prototype_object_getters (ecma_value_t this_arg, /**< this argument */ + uint16_t builtin_routine_id) /**< built-in wide routine identifier */ +{ + ecma_dataview_object_t *obj_p = ecma_op_dataview_get_object (this_arg); + + if (JERRY_UNLIKELY (obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + switch (builtin_routine_id) + { + case ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER: + { + ecma_object_t *buffer_p = obj_p->buffer_p; + ecma_ref_object (buffer_p); + + return ecma_make_object_value (buffer_p); + } + case ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER: + { + if (ecma_arraybuffer_is_detached (obj_p->buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + return ecma_make_uint32_value (obj_p->header.u.cls.u3.length); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER); + + if (ecma_arraybuffer_is_detached (obj_p->buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + return ecma_make_uint32_value (obj_p->byte_offset); + } + } +} /* ecma_builtin_dataview_prototype_object_getters */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_dataview_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + switch (builtin_routine_id) + { + case ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER: + case ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER: + case ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER: + { + return ecma_builtin_dataview_prototype_object_getters (this_arg, builtin_routine_id); + } + case ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32: +#if JERRY_NUMBER_TYPE_FLOAT64 + case ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64: +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + case ECMA_DATAVIEW_PROTOTYPE_GET_INT16: + case ECMA_DATAVIEW_PROTOTYPE_GET_INT32: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT16: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT32: +#if JERRY_BUILTIN_BIGINT + case ECMA_DATAVIEW_PROTOTYPE_GET_BIGINT64: + case ECMA_DATAVIEW_PROTOTYPE_GET_BIGUINT64: +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_GET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + arguments_list_p[1], + ECMA_VALUE_EMPTY, + id); + } + case ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32: +#if JERRY_NUMBER_TYPE_FLOAT64 + case ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64: +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + case ECMA_DATAVIEW_PROTOTYPE_SET_INT16: + case ECMA_DATAVIEW_PROTOTYPE_SET_INT32: + case ECMA_DATAVIEW_PROTOTYPE_SET_UINT16: + case ECMA_DATAVIEW_PROTOTYPE_SET_UINT32: +#if JERRY_BUILTIN_BIGINT + case ECMA_DATAVIEW_PROTOTYPE_SET_BIGINT64: + case ECMA_DATAVIEW_PROTOTYPE_SET_BIGUINT64: +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_SET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + arguments_list_p[2], + arguments_list_p[1], + id); + } + case ECMA_DATAVIEW_PROTOTYPE_GET_INT8: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT8: + { + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_GET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + ECMA_VALUE_FALSE, + ECMA_VALUE_EMPTY, + id); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_SET_INT8 + || builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_SET_UINT8); + ecma_typedarray_type_t id = (ecma_typedarray_type_t) (builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_SET_INT8); + + return ecma_op_dataview_get_set_view_value (this_arg, + arguments_list_p[0], + ECMA_VALUE_FALSE, + arguments_list_p[1], + id); + } + } +} /* ecma_builtin_dataview_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h new file mode 100644 index 00000000..82ef26b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * DataView.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATAVIEW + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 24.2.3 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_DATAVIEW, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.2.4.21 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_DATAVIEW_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32, 2, 1) +#if JERRY_NUMBER_TYPE_FLOAT64 +ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64, 2, 1) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +ROUTINE (LIT_MAGIC_STRING_GET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT8, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT32, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT8, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT32, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32, 2, 2) +#if JERRY_NUMBER_TYPE_FLOAT64 +ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64, 2, 2) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +ROUTINE (LIT_MAGIC_STRING_SET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT8, 1, 2) +ROUTINE (LIT_MAGIC_STRING_SET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT16, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT32, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT8, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT16, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT32, 2, 2) +#if JERRY_BUILTIN_BIGINT +ROUTINE (LIT_MAGIC_STRING_GET_BIGINT64, ECMA_DATAVIEW_PROTOTYPE_GET_BIGINT64, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_BIGUINT64, ECMA_DATAVIEW_PROTOTYPE_GET_BIGUINT64, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_BIGINT64, ECMA_DATAVIEW_PROTOTYPE_SET_BIGINT64, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_BIGUINT64, ECMA_DATAVIEW_PROTOTYPE_SET_BIGUINT64, 2, 2) +#endif /* JERRY_BUILTIN_BIGINT */ + +/* ECMA-262 v6, 24.2.4.1 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BUFFER, ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 24.2.4.2 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 24.2.4.3 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_OFFSET_UL, + ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.cpp new file mode 100644 index 00000000..bfdb33f0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.cpp @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_DATAVIEW + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-dataview.inc.h" +#define BUILTIN_UNDERSCORED_ID dataview +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dataview ECMA DataView object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in DataView object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dataview_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_DATAVIEW_REQUIRES_NEW); +} /* ecma_builtin_dataview_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in DataView object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dataview_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_dataview_create (arguments_list_p, arguments_list_len); +} /* ecma_builtin_dataview_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h new file mode 100644 index 00000000..9b1027cc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * DataView built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATAVIEW + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_DATAVIEW_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.1.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp new file mode 100644 index 00000000..5ad4f2d8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp @@ -0,0 +1,722 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#if JERRY_BUILTIN_DATE + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * Checks whether the function uses UTC time zone. + */ +#define BUILTIN_DATE_FUNCTION_IS_UTC(builtin_routine_id) \ + (((builtin_routine_id) -ECMA_DATE_PROTOTYPE_GET_FULL_YEAR) & 0x1) + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_DATE_PROTOTYPE_ROUTINE_START = 0, + + ECMA_DATE_PROTOTYPE_GET_FULL_YEAR, /* ECMA-262 v5 15.9.5.10 */ + ECMA_DATE_PROTOTYPE_GET_UTC_FULL_YEAR, /* ECMA-262 v5 15.9.5.11 */ +#if JERRY_BUILTIN_ANNEXB + ECMA_DATE_PROTOTYPE_GET_YEAR, /* ECMA-262 v5, AnnexB.B.2.4 */ + ECMA_DATE_PROTOTYPE_GET_UTC_YEAR, /* has no UTC variant */ +#endif /* JERRY_BUILTIN_ANNEXB */ + ECMA_DATE_PROTOTYPE_GET_MONTH, /* ECMA-262 v5 15.9.5.12 */ + ECMA_DATE_PROTOTYPE_GET_UTC_MONTH, /* ECMA-262 v5 15.9.5.13 */ + ECMA_DATE_PROTOTYPE_GET_DATE, /* ECMA-262 v5 15.9.5.14 */ + ECMA_DATE_PROTOTYPE_GET_UTC_DATE, /* ECMA-262 v5 15.9.5.15 */ + ECMA_DATE_PROTOTYPE_GET_DAY, /* ECMA-262 v5 15.9.5.16 */ + ECMA_DATE_PROTOTYPE_GET_UTC_DAY, /* ECMA-262 v5 15.9.5.17 */ + ECMA_DATE_PROTOTYPE_GET_HOURS, /* ECMA-262 v5 15.9.5.18 */ + ECMA_DATE_PROTOTYPE_GET_UTC_HOURS, /* ECMA-262 v5 15.9.5.19 */ + ECMA_DATE_PROTOTYPE_GET_MINUTES, /* ECMA-262 v5 15.9.5.20 */ + ECMA_DATE_PROTOTYPE_GET_UTC_MINUTES, /* ECMA-262 v5 15.9.5.21 */ + ECMA_DATE_PROTOTYPE_GET_SECONDS, /* ECMA-262 v5 15.9.5.22 */ + ECMA_DATE_PROTOTYPE_GET_UTC_SECONDS, /* ECMA-262 v5 15.9.5.23 */ + ECMA_DATE_PROTOTYPE_GET_MILLISECONDS, /* ECMA-262 v5 15.9.5.24 */ + ECMA_DATE_PROTOTYPE_GET_UTC_MILLISECONDS, /* ECMA-262 v5 15.9.5.25 */ + ECMA_DATE_PROTOTYPE_GET_TIMEZONE_OFFSET, /* has no local time zone variant */ + ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET, /* ECMA-262 v5 15.9.5.26 */ + + ECMA_DATE_PROTOTYPE_SET_FULL_YEAR, /* ECMA-262 v5, 15.9.5.40 */ + ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR, /* ECMA-262 v5, 15.9.5.41 */ +#if JERRY_BUILTIN_ANNEXB + ECMA_DATE_PROTOTYPE_SET_YEAR, /* ECMA-262 v5, ECMA-262 v5, AnnexB.B.2.5 */ + ECMA_DATE_PROTOTYPE_SET_UTC_YEAR, /* has no UTC variant */ +#endif /* JERRY_BUILTIN_ANNEXB */ + ECMA_DATE_PROTOTYPE_SET_MONTH, /* ECMA-262 v5, 15.9.5.38 */ + ECMA_DATE_PROTOTYPE_SET_UTC_MONTH, /* ECMA-262 v5, 15.9.5.39 */ + ECMA_DATE_PROTOTYPE_SET_DATE, /* ECMA-262 v5, 15.9.5.36 */ + ECMA_DATE_PROTOTYPE_SET_UTC_DATE, /* ECMA-262 v5, 15.9.5.37 */ + ECMA_DATE_PROTOTYPE_SET_HOURS, /* ECMA-262 v5, 15.9.5.34 */ + ECMA_DATE_PROTOTYPE_SET_UTC_HOURS, /* ECMA-262 v5, 15.9.5.35 */ + ECMA_DATE_PROTOTYPE_SET_MINUTES, /* ECMA-262 v5, 15.9.5.32 */ + ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES, /* ECMA-262 v5, 15.9.5.33 */ + ECMA_DATE_PROTOTYPE_SET_SECONDS, /* ECMA-262 v5, 15.9.5.30 */ + ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS, /* ECMA-262 v5, 15.9.5.31 */ + ECMA_DATE_PROTOTYPE_SET_MILLISECONDS, /* ECMA-262 v5, 15.9.5.28 */ + ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS, /* ECMA-262 v5, 15.9.5.29 */ + + ECMA_DATE_PROTOTYPE_TO_STRING, /* ECMA-262 v5, 15.9.5.2 */ + ECMA_DATE_PROTOTYPE_TO_DATE_STRING, /* ECMA-262 v5, 15.9.5.3 */ + ECMA_DATE_PROTOTYPE_TO_TIME_STRING, /* ECMA-262 v5, 15.9.5.4 */ + ECMA_DATE_PROTOTYPE_TO_ISO_STRING, /* ECMA-262 v5, 15.9.5.43 */ + + ECMA_DATE_PROTOTYPE_GET_TIME, /* ECMA-262 v5, 15.9.5.9 */ + ECMA_DATE_PROTOTYPE_SET_TIME, /* ECMA-262 v5, 15.9.5.27 */ + ECMA_DATE_PROTOTYPE_TO_JSON, /* ECMA-262 v5, 15.9.5.44 */ + + ECMA_DATE_PROTOTYPE_TO_PRIMITIVE, /* ECMA-262 v6 20.3.4.45 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-date-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID date_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dateprototype ECMA Date.prototype object built-in + * @{ + */ + +/** + * The Date.prototype object's 'toJSON' routine + * + * See also: + * ECMA-262 v5, 15.9.5.44 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_to_json (ecma_value_t this_arg) /**< this argument */ +{ + /* 1. */ + ecma_value_t obj = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (obj)) + { + return obj; + } + + /* 2. */ + ecma_value_t tv = ecma_op_to_primitive (obj, ECMA_PREFERRED_TYPE_NUMBER); + + if (ECMA_IS_VALUE_ERROR (tv)) + { + ecma_free_value (obj); + return tv; + } + + /* 3. */ + if (ecma_is_value_number (tv)) + { + ecma_number_t num_value = ecma_get_number_from_value (tv); + + ecma_free_value (tv); + + if (ecma_number_is_nan (num_value) || ecma_number_is_infinity (num_value)) + { + ecma_free_value (obj); + return ECMA_VALUE_NULL; + } + } + else + { + ecma_free_value (tv); + } + + ecma_object_t *value_obj_p = ecma_get_object_from_value (obj); + + /* 4. */ + ecma_value_t ret_value = ecma_op_invoke_by_magic_id (obj, LIT_MAGIC_STRING_TO_ISO_STRING_UL, NULL, 0); + + ecma_deref_object (value_obj_p); + + return ret_value; +} /* ecma_builtin_date_prototype_to_json */ + +/** + * The Date.prototype object's toPrimitive routine + * + * See also: + * ECMA-262 v6, 20.3.4.45 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_to_primitive (ecma_value_t this_arg, /**< this argument */ + ecma_value_t hint_arg) /**< {"default", "number", "string"} */ +{ + if (ecma_is_value_object (this_arg) && ecma_is_value_string (hint_arg)) + { + ecma_string_t *hint_str_p = ecma_get_string_from_value (hint_arg); + + ecma_preferred_type_hint_t hint = ECMA_PREFERRED_TYPE_NO; + + if (hint_str_p == ecma_get_magic_string (LIT_MAGIC_STRING_STRING) + || hint_str_p == ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT)) + { + hint = ECMA_PREFERRED_TYPE_STRING; + } + else if (hint_str_p == ecma_get_magic_string (LIT_MAGIC_STRING_NUMBER)) + { + hint = ECMA_PREFERRED_TYPE_NUMBER; + } + + if (hint != ECMA_PREFERRED_TYPE_NO) + { + return ecma_op_general_object_ordinary_value (ecma_get_object_from_value (this_arg), hint); + } + } + + return ecma_raise_type_error (ECMA_ERR_INVALID_ARGUMENT_TYPE_IN_TOPRIMITIVE); +} /* ecma_builtin_date_prototype_to_primitive */ + +/** + * Dispatch get date functions + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_dispatch_get (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_number_t date_value) /**< date converted to number */ +{ + if (ecma_number_is_nan (date_value)) + { + return ecma_make_nan_value (); + } + + int32_t result; + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_GET_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_GET_UTC_FULL_YEAR: + { + result = ecma_date_year_from_time (date_value); + break; + } +#if JERRY_BUILTIN_ANNEXB + case ECMA_DATE_PROTOTYPE_GET_YEAR: + { + result = (ecma_date_year_from_time (date_value) - 1900); + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_DATE_PROTOTYPE_GET_MONTH: + case ECMA_DATE_PROTOTYPE_GET_UTC_MONTH: + { + result = ecma_date_month_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_DATE: + case ECMA_DATE_PROTOTYPE_GET_UTC_DATE: + { + result = ecma_date_date_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_DAY: + case ECMA_DATE_PROTOTYPE_GET_UTC_DAY: + { + result = ecma_date_week_day (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_HOURS: + case ECMA_DATE_PROTOTYPE_GET_UTC_HOURS: + { + result = ecma_date_hour_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_MINUTES: + case ECMA_DATE_PROTOTYPE_GET_UTC_MINUTES: + { + result = ecma_date_min_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_SECONDS: + case ECMA_DATE_PROTOTYPE_GET_UTC_SECONDS: + { + result = ecma_date_sec_from_time (date_value); + break; + } + case ECMA_DATE_PROTOTYPE_GET_MILLISECONDS: + case ECMA_DATE_PROTOTYPE_GET_UTC_MILLISECONDS: + { + result = ecma_date_ms_from_time (date_value); + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET); + + result = -ecma_date_local_time_zone_adjustment (date_value) / ECMA_DATE_MS_PER_MINUTE; + break; + } + } + + return ecma_make_int32_value (result); +} /* ecma_builtin_date_prototype_dispatch_get */ + +#if JERRY_BUILTIN_ANNEXB + +/** + * Returns true, if the built-in id sets a year. + */ +#define ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE(builtin_routine_id) \ + ((builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_FULL_YEAR \ + || (builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR \ + || (builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_YEAR) + +#else /* !JERRY_BUILTIN_ANNEXB */ + +/** + * Returns true, if the built-in id sets a year. + */ +#define ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE(builtin_routine_id) \ + ((builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_FULL_YEAR \ + || (builtin_routine_id) == ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR) + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * Dispatch set date functions + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_prototype_dispatch_set (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_object_t *object_p, /**< date object */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_number_t converted_number[4]; + uint32_t conversions = 0; + + /* If the first argument is not specified, it is always converted to NaN. */ + converted_number[0] = ecma_number_make_nan (); + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ANNEXB + case ECMA_DATE_PROTOTYPE_SET_YEAR: +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_DATE_PROTOTYPE_SET_DATE: + case ECMA_DATE_PROTOTYPE_SET_UTC_DATE: + case ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS: + case ECMA_DATE_PROTOTYPE_SET_MILLISECONDS: + { + conversions = 1; + break; + } + case ECMA_DATE_PROTOTYPE_SET_MONTH: + case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH: + case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS: + case ECMA_DATE_PROTOTYPE_SET_SECONDS: + { + conversions = 2; + break; + } + case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_SET_MINUTES: + case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES: + { + conversions = 3; + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_HOURS + || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_HOURS); + + conversions = 4; + break; + } + } + + if (conversions > arguments_number) + { + conversions = arguments_number; + } + + for (uint32_t i = 0; i < conversions; i++) + { + ecma_value_t value = ecma_op_to_number (arguments_list[i], &converted_number[i]); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + + ecma_date_object_t *date_object_p = (ecma_date_object_t *) object_p; + ecma_number_t *date_value_p = &date_object_p->date_value; + ecma_number_t date_value = *date_value_p; + + if (!BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id)) + { + ecma_number_t local_tza; + + if (date_object_p->header.u.cls.u1.date_flags & ECMA_DATE_TZA_SET) + { + local_tza = date_object_p->header.u.cls.u3.tza; + JERRY_ASSERT (local_tza == ecma_date_local_time_zone_adjustment (date_value)); + } + else + { + local_tza = ecma_date_local_time_zone_adjustment (date_value); + } + + date_value += local_tza; + } + + ecma_number_t day_part; + ecma_number_t time_part; + + if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_SET_UTC_DATE) + { + if (ecma_number_is_nan (date_value)) + { + if (!ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE (builtin_routine_id)) + { + return ecma_make_number_value (date_value); + } + + date_value = ECMA_NUMBER_ZERO; + } + + time_part = ecma_date_time_in_day_from_time (date_value); + + ecma_number_t year = ecma_date_year_from_time (date_value); + ecma_number_t month = ecma_date_month_from_time (date_value); + ecma_number_t day = ecma_date_date_from_time (date_value); + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR: + case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR: + { + year = converted_number[0]; + if (conversions >= 2) + { + month = converted_number[1]; + } + if (conversions >= 3) + { + day = converted_number[2]; + } + break; + } +#if JERRY_BUILTIN_ANNEXB + case ECMA_DATE_PROTOTYPE_SET_YEAR: + { + if (ecma_number_is_nan (converted_number[0])) + { + *date_value_p = converted_number[0]; + date_object_p->header.u.cls.u1.date_flags &= (uint8_t) ~ECMA_DATE_TZA_SET; + return ecma_make_number_value (converted_number[0]); + } + + year = ecma_number_trunc (converted_number[0]); + if (year >= 0 && year <= 99) + { + year += 1900; + } + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_DATE_PROTOTYPE_SET_MONTH: + case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH: + { + month = converted_number[0]; + if (conversions >= 2) + { + day = converted_number[1]; + } + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_DATE + || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_DATE); + + day = converted_number[0]; + break; + } + } + + day_part = ecma_date_make_day (year, month, day); + +#if JERRY_BUILTIN_ANNEXB + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_YEAR) + { + if (ecma_number_is_nan (converted_number[0])) + { + day_part = 0; + time_part = converted_number[0]; + } + } +#endif /* JERRY_BUILTIN_ANNEXB */ + } + else + { + if (ecma_number_is_nan (date_value)) + { + return ecma_make_number_value (date_value); + } + + day_part = ecma_date_day_from_time (date_value) * (ecma_number_t) ECMA_DATE_MS_PER_DAY; + + ecma_number_t hour = ecma_date_hour_from_time (date_value); + ecma_number_t min = ecma_date_min_from_time (date_value); + ecma_number_t sec = ecma_date_sec_from_time (date_value); + ecma_number_t ms = ecma_date_ms_from_time (date_value); + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_SET_HOURS: + case ECMA_DATE_PROTOTYPE_SET_UTC_HOURS: + { + hour = converted_number[0]; + if (conversions >= 2) + { + min = converted_number[1]; + } + if (conversions >= 3) + { + sec = converted_number[2]; + } + if (conversions >= 4) + { + ms = converted_number[3]; + } + break; + } + case ECMA_DATE_PROTOTYPE_SET_MINUTES: + case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES: + { + min = converted_number[0]; + if (conversions >= 2) + { + sec = converted_number[1]; + } + if (conversions >= 3) + { + ms = converted_number[2]; + } + break; + } + case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS: + case ECMA_DATE_PROTOTYPE_SET_SECONDS: + { + sec = converted_number[0]; + if (conversions >= 2) + { + ms = converted_number[1]; + } + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS + || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_MILLISECONDS); + + ms = converted_number[0]; + break; + } + } + + time_part = ecma_date_make_time (hour, min, sec, ms); + } + + bool is_utc = BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id); + + ecma_number_t full_date = ecma_date_make_date (day_part, time_part); + + if (!is_utc) + { + full_date = ecma_date_utc (full_date); + } + + full_date = ecma_date_time_clip (full_date); + + *date_value_p = full_date; + + date_object_p->header.u.cls.u1.date_flags &= (uint8_t) ~ECMA_DATE_TZA_SET; + + return ecma_make_number_value (full_date); +} /* ecma_builtin_date_prototype_dispatch_set */ + +#undef ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_date_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_JSON)) + { + return ecma_builtin_date_prototype_to_json (this_arg); + } + + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_PRIMITIVE)) + { + return ecma_builtin_date_prototype_to_primitive (this_arg, arguments_list[0]); + } + + if (!ecma_is_value_object (this_arg) + || !ecma_object_class_is (ecma_get_object_from_value (this_arg), ECMA_OBJECT_CLASS_DATE)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT); + } + + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + + ecma_date_object_t *date_object_p = (ecma_date_object_t *) this_obj_p; + ecma_number_t *date_value_p = &date_object_p->date_value; + ecma_number_t date_value = *date_value_p; + + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_GET_TIME) + { + return ecma_make_number_value (date_value); + } + + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_TIME) + { + ecma_number_t time_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (arguments_list[0], &time_num))) + { + return ECMA_VALUE_ERROR; + } + + *date_value_p = ecma_date_time_clip (time_num); + date_object_p->header.u.cls.u1.date_flags &= (uint8_t) ~ECMA_DATE_TZA_SET; + + return ecma_make_number_value (*date_value_p); + } + + if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS) + { + if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET) + { + if (!BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id)) + { + ecma_number_t local_tza; + + if (date_object_p->header.u.cls.u1.date_flags & ECMA_DATE_TZA_SET) + { + local_tza = date_object_p->header.u.cls.u3.tza; + JERRY_ASSERT (local_tza == ecma_date_local_time_zone_adjustment (date_value)); + } + else + { + local_tza = ecma_date_local_time_zone_adjustment (date_value); + JERRY_ASSERT (local_tza <= INT32_MAX && local_tza >= INT32_MIN); + date_object_p->header.u.cls.u3.tza = (int32_t) local_tza; + date_object_p->header.u.cls.u1.date_flags |= ECMA_DATE_TZA_SET; + } + + date_value += local_tza; + } + + return ecma_builtin_date_prototype_dispatch_get (builtin_routine_id, date_value); + } + + return ecma_builtin_date_prototype_dispatch_set (builtin_routine_id, this_obj_p, arguments_list, arguments_number); + } + + if (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_ISO_STRING) + { + if (ecma_number_is_nan (date_value)) + { + return ecma_raise_range_error (ECMA_ERR_DATE_MUST_BE_A_FINITE_NUMBER); + } + + return ecma_date_value_to_iso_string (date_value); + } + + if (ecma_number_is_nan (date_value)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_INVALID_DATE_UL); + } + + switch (builtin_routine_id) + { + case ECMA_DATE_PROTOTYPE_TO_STRING: + { + return ecma_date_value_to_string (date_value); + } + case ECMA_DATE_PROTOTYPE_TO_DATE_STRING: + { + return ecma_date_value_to_date_string (date_value); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_TO_TIME_STRING); + + return ecma_date_value_to_time_string (date_value); + } + } +} /* ecma_builtin_date_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATE */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.inc.h new file mode 100644 index 00000000..a960cc45 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.inc.h @@ -0,0 +1,83 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Date.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATE + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_DATE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_DATE_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_DATE_STRING_UL, ECMA_DATE_PROTOTYPE_TO_DATE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_TIME_STRING_UL, ECMA_DATE_PROTOTYPE_TO_TIME_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_DATE_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL, ECMA_DATE_PROTOTYPE_TO_DATE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL, ECMA_DATE_PROTOTYPE_TO_TIME_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_DATE_PROTOTYPE_GET_TIME, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_TIME_UL, ECMA_DATE_PROTOTYPE_GET_TIME, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_GET_FULL_YEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_GET_UTC_FULL_YEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_MONTH_UL, ECMA_DATE_PROTOTYPE_GET_MONTH, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_MONTH_UL, ECMA_DATE_PROTOTYPE_GET_UTC_MONTH, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_DATE_UL, ECMA_DATE_PROTOTYPE_GET_DATE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_DATE_UL, ECMA_DATE_PROTOTYPE_GET_UTC_DATE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_DAY_UL, ECMA_DATE_PROTOTYPE_GET_DAY, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_DAY_UL, ECMA_DATE_PROTOTYPE_GET_UTC_DAY, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_HOURS_UL, ECMA_DATE_PROTOTYPE_GET_HOURS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_HOURS_UL, ECMA_DATE_PROTOTYPE_GET_UTC_HOURS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_MINUTES_UL, ECMA_DATE_PROTOTYPE_GET_MINUTES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_MINUTES_UL, ECMA_DATE_PROTOTYPE_GET_UTC_MINUTES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_SECONDS_UL, ECMA_DATE_PROTOTYPE_GET_SECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_SECONDS_UL, ECMA_DATE_PROTOTYPE_GET_UTC_SECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_GET_MILLISECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_UTC_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_GET_UTC_MILLISECONDS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_GET_TIMEZONE_OFFSET_UL, ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SET_TIME_UL, ECMA_DATE_PROTOTYPE_SET_TIME, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_SET_MILLISECONDS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL, ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_SECONDS_UL, ECMA_DATE_PROTOTYPE_SET_SECONDS, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_SECONDS_UL, ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_MINUTES_UL, ECMA_DATE_PROTOTYPE_SET_MINUTES, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_MINUTES_UL, ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_SET_HOURS_UL, ECMA_DATE_PROTOTYPE_SET_HOURS, NON_FIXED, 4) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_HOURS_UL, ECMA_DATE_PROTOTYPE_SET_UTC_HOURS, NON_FIXED, 4) +ROUTINE (LIT_MAGIC_STRING_SET_DATE_UL, ECMA_DATE_PROTOTYPE_SET_DATE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_DATE_UL, ECMA_DATE_PROTOTYPE_SET_UTC_DATE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_MONTH_UL, ECMA_DATE_PROTOTYPE_SET_MONTH, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_MONTH_UL, ECMA_DATE_PROTOTYPE_SET_UTC_MONTH, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SET_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_SET_FULL_YEAR, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_SET_UTC_FULL_YEAR_UL, ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_TO_ISO_STRING_UL, ECMA_DATE_PROTOTYPE_TO_ISO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_JSON_UL, ECMA_DATE_PROTOTYPE_TO_JSON, 1, 1) +ROUTINE_CONFIGURABLE_ONLY (LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, ECMA_DATE_PROTOTYPE_TO_PRIMITIVE, 1, 1) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_UTC_STRING_UL, + LIT_MAGIC_STRING_TO_UTC_STRING_UL, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#if JERRY_BUILTIN_ANNEXB +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_GMT_STRING_UL, + LIT_MAGIC_STRING_TO_UTC_STRING_UL, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +ROUTINE (LIT_MAGIC_STRING_GET_YEAR_UL, ECMA_DATE_PROTOTYPE_GET_YEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SET_YEAR_UL, ECMA_DATE_PROTOTYPE_SET_YEAR, 1, 1) + +#endif /* JERRY_BUILTIN_ANNEXB */ + +#endif /* JERRY_BUILTIN_DATE */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp new file mode 100644 index 00000000..c9b0d5de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp @@ -0,0 +1,874 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_DATE + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_DATE_ROUTINE_START = 0, + ECMA_DATE_ROUTINE_PARSE, + ECMA_DATE_ROUTINE_UTC, + ECMA_DATE_ROUTINE_NOW, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-date.inc.h" +#define BUILTIN_UNDERSCORED_ID date +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup date ECMA Date object built-in + * @{ + */ + +/** + * Encode minimum/maximum limits + * + * See: ecma_date_parse_date_chars + * + * @param min: 8 bits unsigned number + * @param max: 24 bits unsigned number + */ +#define ECMA_DATE_LIMIT(min, max) (min << 24 | max) + +/** + * Decode the minimum value from the encoded limit + */ +#define ECMA_DATE_LIMIT_MIN(limit) (limit >> 24) + +/** + * Decode the maximum value from the encoded limit + */ +#define ECMA_DATE_LIMIT_MAX(limit) (limit & ((1 << 24) - 1)) + +/** + * Helper function to try to parse a part of a date string + * + * @return NaN if cannot read from string, ToNumber() otherwise + */ +static ecma_number_t +ecma_date_parse_date_chars (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */ + uint32_t num_of_chars, /**< number of characters to read and convert */ + uint32_t limit) /**< minimum/maximum valid value */ +{ + JERRY_ASSERT (num_of_chars > 0 && num_of_chars <= 6); + + if (*str_p + num_of_chars > str_end_p) + { + return ecma_number_make_nan (); + } + + str_end_p = *str_p + num_of_chars; + + uint32_t num = 0; + + while (num_of_chars--) + { + lit_utf8_byte_t c = **str_p; + if (!lit_char_is_decimal_digit (c)) + { + return ecma_number_make_nan (); + } + + num = (num * 10) + (uint32_t) ((c - LIT_CHAR_0)); + (*str_p)++; + } + + if (num >= ECMA_DATE_LIMIT_MIN (limit) && num <= ECMA_DATE_LIMIT_MAX (limit)) + { + return (ecma_number_t) num; + } + + return ecma_number_make_nan (); +} /* ecma_date_parse_date_chars */ + +/** + * Helper function to try to parse a special chracter (+,-,T,Z,:,.) in a date string + * + * @return true if the first character is same as the expected, false otherwise + */ +static bool +ecma_date_parse_special_char (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */ + ecma_char_t expected_char) /**< expected character */ +{ + if ((*str_p < str_end_p) && (**str_p == expected_char)) + { + (*str_p)++; + return true; + } + + return false; +} /* ecma_date_parse_special_char */ + +static inline bool +ecma_date_check_two_chars (const lit_utf8_byte_t *str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */ + ecma_char_t expected_char1, /**< first expected character */ + ecma_char_t expected_char2) /**< second expected character */ +{ + return (str_p < str_end_p && (*str_p == expected_char1 || *str_p == expected_char2)); +} /* ecma_date_check_two_chars */ + +/** + * Helper function to try to parse a 4-5-6 digit year with optional negative sign in a date string + * + * Date.prototype.toString() and Date.prototype.toUTCString() emits year + * in this format and Date.parse() should parse this format too. + * + * @return the parsed year or NaN. + */ +static ecma_number_t +ecma_date_parse_year (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */ +{ + bool is_year_sign_negative = ecma_date_parse_special_char (str_p, str_end_p, LIT_CHAR_MINUS); + const lit_utf8_byte_t *str_start_p = *str_p; + int32_t parsed_year = 0; + + while ((str_start_p - *str_p < 6) && (str_start_p < str_end_p) && lit_char_is_decimal_digit (*str_start_p)) + { + parsed_year = 10 * parsed_year + *str_start_p - LIT_CHAR_0; + str_start_p++; + } + + if (str_start_p - *str_p >= 4) + { + *str_p = str_start_p; + return is_year_sign_negative ? -parsed_year : parsed_year; + } + + return ecma_number_make_nan (); +} /* ecma_date_parse_year */ + +/** + * Helper function to try to parse a day name in a date string + * Valid day names: Sun, Mon, Tue, Wed, Thu, Fri, Sat + * See also: + * ECMA-262 v9, 20.3.4.41.2 Table 46 + * + * @return true if the string starts with a valid day name, false otherwise + */ +static bool +ecma_date_parse_day_name (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */ +{ + if (*str_p + 3 < str_end_p) + { + for (uint32_t i = 0; i < 7; i++) + { + if (!memcmp (day_names_p[i], *str_p, 3)) + { + (*str_p) += 3; + return true; + } + } + } + return false; +} /* ecma_date_parse_day_name */ + +/** + * Helper function to try to parse a month name in a date string + * Valid month names: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec + * See also: + * ECMA-262 v9, 20.3.4.41.2 Table 47 + * + * @return number of the month if the string starts with a valid month name, 0 otherwise + */ +static uint32_t +ecma_date_parse_month_name (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ + const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */ +{ + if (*str_p + 3 < str_end_p) + { + for (uint32_t i = 0; i < 12; i++) + { + if (!memcmp (month_names_p[i], *str_p, 3)) + { + (*str_p) += 3; + return (i + 1); + } + } + } + return 0; +} /* ecma_date_parse_month_name */ + +/** + * Calculate MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)) for Date constructor and UTC + * + * See also: + * ECMA-262 v11, 20.4.3.4 + * + * @return false - if the operation fails + * true - otherwise + */ +static bool +ecma_date_construct_helper (const ecma_value_t *args, /**< arguments passed to the Date constructor */ + uint32_t args_len, /**< number of arguments */ + ecma_number_t *tv_p) /**< [out] time value */ +{ + ecma_number_t date_nums[7] = { + ECMA_NUMBER_ZERO, /* year */ + ECMA_NUMBER_ZERO, /* month */ + ECMA_NUMBER_ONE, /* date */ + ECMA_NUMBER_ZERO, /* hours */ + ECMA_NUMBER_ZERO, /* minutes */ + ECMA_NUMBER_ZERO, /* seconds */ + ECMA_NUMBER_ZERO /* miliseconds */ + }; + + args_len = JERRY_MIN (args_len, sizeof (date_nums) / sizeof (date_nums[0])); + + /* 1-7. */ + for (uint32_t i = 0; i < args_len; i++) + { + ecma_value_t status = ecma_op_to_number (args[i], date_nums + i); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return false; + } + } + + /* 8. */ + if (!ecma_number_is_nan (date_nums[0])) + { + /* 9.a */ + ecma_number_t yi = ecma_number_trunc (date_nums[0]); + + /* 9.b */ + if (yi >= 0 && yi <= 99) + { + date_nums[0] = 1900 + yi; + } + } + + /* 10. */ + *tv_p = ecma_date_make_date (ecma_date_make_day (date_nums[0], date_nums[1], date_nums[2]), + ecma_date_make_time (date_nums[3], date_nums[4], date_nums[5], date_nums[6])); + return true; +} /* ecma_date_construct_helper */ + +/** + * Helper function used by ecma_builtin_date_parse + * + * See also: + * ECMA-262 v5, 15.9.4.2 Date.parse (string) + * ECMA-262 v5, 15.9.1.15 Date Time String Format + * + * @return the parsed date as ecma_number_t or NaN otherwise + */ +static ecma_number_t +ecma_builtin_date_parse_basic (const lit_utf8_byte_t *date_str_curr_p, /**< date string start */ + const lit_utf8_byte_t *date_str_end_p) /**< date string end */ +{ + /* 1. read year */ + + uint32_t year_digits = 4; + uint32_t year_limit = 9999; + + bool is_year_sign_negative = false; + + if (ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_MINUS, LIT_CHAR_PLUS)) + { + is_year_sign_negative = (*date_str_curr_p++ == LIT_CHAR_MINUS); + year_digits = 6; + year_limit = 999999; + } + + ecma_number_t year = + ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, year_digits, ECMA_DATE_LIMIT (0, year_limit)); + if (is_year_sign_negative) + { + year = -year; + } + + if (ecma_number_is_nan (year)) + { + return year; + } + + ecma_number_t month = ECMA_NUMBER_ONE; + ecma_number_t day = ECMA_NUMBER_ONE; + ecma_number_t time = ECMA_NUMBER_ZERO; + + /* 2. read month if any */ + if (ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_MINUS, LIT_CHAR_SLASH)) + { + lit_utf8_byte_t separator = *date_str_curr_p++; + month = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (1, 12)); + + /* 3. read day if any */ + if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, separator)) + { + day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (1, 31)); + } + } + + bool is_utc = true; + /* 4. read time if any */ + if (ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_UPPERCASE_T, LIT_CHAR_SP)) + { + date_str_curr_p++; + + ecma_number_t hours = ECMA_NUMBER_ZERO; + ecma_number_t minutes = ECMA_NUMBER_ZERO; + ecma_number_t seconds = ECMA_NUMBER_ZERO; + ecma_number_t milliseconds = ECMA_NUMBER_ZERO; + + /* 'HH:mm' must present */ + if (date_str_end_p - date_str_curr_p < 5) + { + return ecma_number_make_nan (); + } + + /* 4.1 read hours and minutes */ + hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return ecma_number_make_nan (); + } + + minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + /* 4.2 read seconds if any */ + if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + seconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + /* 4.3 read milliseconds if any */ + if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_DOT)) + { + milliseconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 3, ECMA_DATE_LIMIT (0, 999)); + } + } + + if (hours == 24 && (minutes != 0 || seconds != 0 || milliseconds != 0)) + { + return ecma_number_make_nan (); + } + + time = ecma_date_make_time (hours, minutes, seconds, milliseconds); + + if (ecma_number_is_nan (time)) + { + return time; + } + + /* 4.4 read timezone if any */ + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_UPPERCASE_Z)) + { + if ((date_str_end_p - date_str_curr_p) == 6 + && (*date_str_curr_p == LIT_CHAR_MINUS || *date_str_curr_p == LIT_CHAR_PLUS)) + { + bool is_timezone_sign_negative = (*date_str_curr_p++ == LIT_CHAR_MINUS); + /* read hours and minutes */ + hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (hours == 24) + { + hours = ECMA_NUMBER_ZERO; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return ecma_number_make_nan (); + } + + minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + ecma_number_t timezone_offset = ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); + time += is_timezone_sign_negative ? timezone_offset : -timezone_offset; + } + else + { + is_utc = false; + } + } + } + + if (date_str_curr_p < date_str_end_p) + { + return ecma_number_make_nan (); + } + + ecma_number_t date = ecma_date_make_day (year, month - 1, day); + ecma_number_t result_date = ecma_date_make_date (date, time); + + if (!is_utc) + { + result_date = ecma_date_utc (result_date); + } + + return result_date; +} /* ecma_builtin_date_parse_basic */ + +/** + * Helper function used by ecma_builtin_date_parse + * + * See also: + * ECMA-262 v5, 15.9.4.2 Date.parse (string) + * ECMA-262 v9, 20.3.4.41 Date.prototype.toString () + * ECMA-262 v9, 20.3.4.43 Date.prototype.toUTCString () + * + * Used by: ecma_builtin_date_parse + * + * @return the parsed date as ecma_number_t or NaN otherwise + */ +static ecma_number_t +ecma_builtin_date_parse_toString_formats (const lit_utf8_byte_t *date_str_curr_p, const lit_utf8_byte_t *date_str_end_p) +{ + const ecma_number_t nan = ecma_number_make_nan (); + + if (!ecma_date_parse_day_name (&date_str_curr_p, date_str_end_p)) + { + return nan; + } + + const bool is_toUTCString_format = ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COMMA); + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + ecma_number_t month = 0; + ecma_number_t day = 0; + if (is_toUTCString_format) + { + day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 31)); + + if (ecma_number_is_nan (day)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + month = ecma_date_parse_month_name (&date_str_curr_p, date_str_end_p); + + if (month == 0) + { + return ecma_number_make_nan (); + } + } + else + { + month = ecma_date_parse_month_name (&date_str_curr_p, date_str_end_p); + + if (month == 0) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 31)); + + if (ecma_number_is_nan (day)) + { + return nan; + } + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + ecma_number_t year = ecma_date_parse_year (&date_str_curr_p, date_str_end_p); + + if (ecma_number_is_nan (year)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_SP)) + { + return nan; + } + + ecma_number_t hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (ecma_number_is_nan (hours)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return nan; + } + + ecma_number_t minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + if (ecma_number_is_nan (minutes)) + { + return nan; + } + + if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, LIT_CHAR_COLON)) + { + return nan; + } + + ecma_number_t seconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + if (ecma_number_is_nan (seconds)) + { + return nan; + } + + if (hours == 24 && (minutes != 0 || seconds != 0)) + { + return nan; + } + + const char gmt_p[] = " GMT"; + if (date_str_end_p - date_str_curr_p < 4 || memcmp (date_str_curr_p, gmt_p, 4) != 0) + { + return nan; + } + + date_str_curr_p += 4; + + ecma_number_t time = ecma_date_make_time (hours, minutes, seconds, 0); + + if (!is_toUTCString_format) + { + if (!ecma_date_check_two_chars (date_str_curr_p, date_str_end_p, LIT_CHAR_MINUS, LIT_CHAR_PLUS)) + { + return nan; + } + + bool is_timezone_sign_negative = (*date_str_curr_p++ == LIT_CHAR_MINUS); + + hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 24)); + + if (ecma_number_is_nan (hours)) + { + return nan; + } + + if (hours == 24) + { + hours = ECMA_NUMBER_ZERO; + } + + minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, ECMA_DATE_LIMIT (0, 59)); + + if (ecma_number_is_nan (minutes)) + { + return nan; + } + + ecma_number_t timezone_offset = ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); + + time += is_timezone_sign_negative ? timezone_offset : -timezone_offset; + } + + if (date_str_curr_p < date_str_end_p) + { + return nan; + } + + ecma_number_t date = ecma_date_make_day (year, month - 1, day); + return ecma_date_make_date (date, time); +} /* ecma_builtin_date_parse_toString_formats */ + +/** + * The Date object's 'parse' routine + * + * See also: + * ECMA-262 v5, 15.9.4.2 Date.parse (string) + * ECMA-262 v5, 15.9.1.15 Date Time String Format + * ECMA-262 v9, 20.3.4.41 Date.prototype.toString () + * ECMA-262 v9, 20.3.4.43 Date.prototype.toUTCString () + * + * @return parsed time + */ +static ecma_number_t +ecma_builtin_date_parse (ecma_string_t *string_p) /**< string */ +{ + ECMA_STRING_TO_UTF8_STRING (string_p, str_p, str_size); + const lit_utf8_byte_t *date_str_curr_p = str_p; + const lit_utf8_byte_t *date_str_end_p = str_p + str_size; + + /* try to parse date string as ISO string - ECMA-262 v5, 15.9.1.15 */ + ecma_number_t tv = ecma_builtin_date_parse_basic (date_str_curr_p, date_str_end_p); + + if (ecma_number_is_nan (tv)) + { + /* try to parse date string in Date.prototype.toString() or toUTCString() format */ + tv = ecma_builtin_date_parse_toString_formats (date_str_curr_p, date_str_end_p); + } + + ECMA_FINALIZE_UTF8_STRING (str_p, str_size); + + return tv; +} /* ecma_builtin_date_parse */ + +/** + * The Date object's 'UTC' routine + * + * See also: + * ECMA-262 v5, 15.9.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_date_utc (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number < 1) + { + return ecma_make_nan_value (); + } + + ecma_number_t tv; + + if (!ecma_date_construct_helper (args, args_number, &tv)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_number_value ((ecma_number_t) ecma_date_time_clip (tv)); +} /* ecma_builtin_date_utc */ + +/** + * Helper method to get the current time + * + * @return ecma_number_t + */ +static ecma_number_t +ecma_builtin_date_now_helper (void) +{ + return floor (DOUBLE_TO_ECMA_NUMBER_T (jerry_port_current_time ())); +} /* ecma_builtin_date_now_helper */ + +/** + * Construct a date object with the given [[DateValue]] + * + * Note: New target must be a valid object + * + * @return ECMA_VALUE_ERROR - if the operation fails + * constructed date object - otherwise + */ +static ecma_value_t +ecma_builtin_date_create (ecma_number_t tv) +{ + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) != NULL); + + ecma_object_t *prototype_obj_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_DATE_PROTOTYPE); + + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, sizeof (ecma_date_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (prototype_obj_p); + + ecma_date_object_t *date_object_p = (ecma_date_object_t *) obj_p; + date_object_p->header.u.cls.type = ECMA_OBJECT_CLASS_DATE; + date_object_p->header.u.cls.u1.date_flags = ECMA_DATE_TZA_NONE; + date_object_p->header.u.cls.u3.tza = 0; + date_object_p->date_value = tv; + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_date_create */ + +/** + * Handle calling [[Call]] of built-in Date object + * + * See also: + * ECMA-262 v5, 15.9.2.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_date_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_UNUSED (arguments_list_p); + JERRY_UNUSED (arguments_list_len); + + return ecma_date_value_to_string (ecma_builtin_date_now_helper ()); +} /* ecma_builtin_date_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Date object + * + * See also: + * ECMA-262 v5, 15.9.3.1 + * ECMA-262 v11, 20.4.2 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_date_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + /* 20.4.2.3 */ + if (arguments_list_len == 0) + { + return ecma_builtin_date_create (ecma_builtin_date_now_helper ()); + } + + ecma_number_t tv; + /* 20.4.2.2 */ + if (arguments_list_len == 1) + { + ecma_value_t argument = arguments_list_p[0]; + + /* 4.a */ + if (ecma_is_value_object (argument) + && ecma_object_class_is (ecma_get_object_from_value (argument), ECMA_OBJECT_CLASS_DATE)) + { + return ecma_builtin_date_create (((ecma_date_object_t *) ecma_get_object_from_value (argument))->date_value); + } + /* 4.b */ + ecma_value_t primitive = ecma_op_to_primitive (argument, ECMA_PREFERRED_TYPE_NO); + + if (ECMA_IS_VALUE_ERROR (primitive)) + { + return primitive; + } + + if (ecma_is_value_string (primitive)) + { + ecma_string_t *prim_str_p = ecma_get_string_from_value (primitive); + tv = ecma_builtin_date_parse (prim_str_p); + ecma_deref_ecma_string (prim_str_p); + } + else + { + ecma_value_t prim_value = ecma_op_to_number (primitive, &tv); + ecma_free_value (primitive); + + if (ECMA_IS_VALUE_ERROR (prim_value)) + { + return prim_value; + } + } + } + /* 20.4.2.1 */ + else if (ecma_date_construct_helper (arguments_list_p, arguments_list_len, &tv)) + { + tv = ecma_date_utc (tv); + } + else + { + return ECMA_VALUE_ERROR; + } + + return ecma_builtin_date_create (ecma_date_time_clip (tv)); +} /* ecma_builtin_date_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_date_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + switch (builtin_routine_id) + { + case ECMA_DATE_ROUTINE_NOW: + { + return ecma_make_number_value (ecma_builtin_date_now_helper ()); + } + case ECMA_DATE_ROUTINE_UTC: + { + return ecma_builtin_date_utc (arguments_list_p, arguments_number); + } + case ECMA_DATE_ROUTINE_PARSE: + { + if (arguments_number < 1) + { + return ecma_make_nan_value (); + } + + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_make_number_value (ecma_date_time_clip (ecma_builtin_date_parse (str_p))); + ecma_deref_ecma_string (str_p); + + return result; + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_date_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATE */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h new file mode 100644 index 00000000..a50ac00f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Date built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_DATE + +/* ECMA-262 v5, 15.9.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_DATE_PROTOTYPE, ECMA_PROPERTY_FIXED) + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 7, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +ROUTINE (LIT_MAGIC_STRING_PARSE, ECMA_DATE_ROUTINE_PARSE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_UTC_U, ECMA_DATE_ROUTINE_UTC, NON_FIXED, 7) +ROUTINE (LIT_MAGIC_STRING_NOW, ECMA_DATE_ROUTINE_NOW, 0, 0) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_DATE_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_DATE */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.cpp new file mode 100644 index 00000000..db69f1b9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.cpp @@ -0,0 +1,180 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ERROR_PROTOTYPE_ROUTINE_START = 0, + ECMA_ERROR_PROTOTYPE_ROUTINE_TO_STRING, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-error-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup errorprototype ECMA Error.prototype object built-in + * @{ + */ + +/** + * Helper method to get a property value from an error object + * + * @return ecma_string_t + */ +static ecma_string_t * +ecma_builtin_error_prototype_object_to_string_helper (ecma_object_t *obj_p, /**< error object */ + lit_magic_string_id_t property_id, /**< property id */ + lit_magic_string_id_t default_value) /**< default prop value */ +{ + ecma_value_t prop_value = ecma_op_object_get_by_magic_id (obj_p, property_id); + + if (ECMA_IS_VALUE_ERROR (prop_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (prop_value)) + { + return ecma_get_magic_string (default_value); + } + + ecma_string_t *ret_str_p = ecma_op_to_string (prop_value); + ecma_free_value (prop_value); + + return ret_str_p; +} /* ecma_builtin_error_prototype_object_to_string_helper */ + +/** + * The Error.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.11.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_error_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + /* 2. */ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); + + ecma_string_t *name_string_p = + ecma_builtin_error_prototype_object_to_string_helper (obj_p, LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ERROR_UL); + + if (JERRY_UNLIKELY (name_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *msg_string_p = + ecma_builtin_error_prototype_object_to_string_helper (obj_p, LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY); + + if (JERRY_UNLIKELY (msg_string_p == NULL)) + { + ecma_deref_ecma_string (name_string_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_string_is_empty (name_string_p)) + { + return ecma_make_string_value (msg_string_p); + } + + if (ecma_string_is_empty (msg_string_p)) + { + return ecma_make_string_value (name_string_p); + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (name_string_p); + + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) ": ", 2); + ecma_stringbuilder_append (&builder, msg_string_p); + + ecma_deref_ecma_string (name_string_p); + ecma_deref_ecma_string (msg_string_p); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_error_prototype_object_to_string */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_error_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments passed to + * routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_number, arguments_list_p); + + switch (builtin_routine_id) + { + case ECMA_ERROR_PROTOTYPE_ROUTINE_TO_STRING: + { + return ecma_builtin_error_prototype_object_to_string (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_error_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.inc.h new file mode 100644 index 00000000..751094ca --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Error.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.4.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.4.3 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_ERROR_PROTOTYPE_ROUTINE_TO_STRING, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.cpp new file mode 100644 index 00000000..846186a1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.cpp @@ -0,0 +1,93 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-error.inc.h" +#define BUILTIN_UNDERSCORED_ID error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup error ECMA Error object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Error object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_COMMON, arguments_list_p, arguments_list_len); +} /* ecma_builtin_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Error object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h new file mode 100644 index 00000000..d8cff1bd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Error built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.cpp new file mode 100644 index 00000000..37588033 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-evalerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID eval_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h new file mode 100644 index 00000000..1f13dd2f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * EvalError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_EVAL_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_EVAL_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.cpp new file mode 100644 index 00000000..341d179b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-evalerror.inc.h" +#define BUILTIN_UNDERSCORED_ID eval_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup evalerror ECMA EvalError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in EvalError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_eval_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_EVAL, arguments_list_p, arguments_list_len); +} /* ecma_builtin_eval_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in EvalError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_eval_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_eval_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_eval_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h new file mode 100644 index 00000000..29c8f966 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * EvalError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_EVAL_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp new file mode 100644 index 00000000..555f5f3d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp @@ -0,0 +1,550 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-function-prototype.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_FUNCTION_PROTOTYPE_ROUTINE_START = 0, + ECMA_FUNCTION_PROTOTYPE_TO_STRING, + ECMA_FUNCTION_PROTOTYPE_CALL, + ECMA_FUNCTION_PROTOTYPE_APPLY, + ECMA_FUNCTION_PROTOTYPE_BIND, + ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-function-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID function_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup functionprototype ECMA Function.prototype object built-in + * @{ + */ + +/** + * Maximum number of arguments for an apply function. + */ +#define ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT 65535 + +/** + * The Function.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.3.4.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_function_prototype_object_to_string (ecma_object_t *func_obj_p) /**< this argument object */ +{ + if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE); + } + +#if JERRY_FUNCTION_TO_STRING + const ecma_compiled_code_t *bytecode_p; + bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) func_obj_p); + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_p); + uint8_t extended_info = *extended_info_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE) + { + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + ecma_extended_info_decode_vlq (&extended_info_p); + } + + uint32_t range_start = ecma_extended_info_decode_vlq (&extended_info_p); + uint32_t range_size = ecma_extended_info_decode_vlq (&extended_info_p); + ecma_value_t source_code; + + if (!(extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS)) + { + source_code = script_p->source_code; +#if JERRY_SNAPSHOT_EXEC + if (ecma_is_value_magic_string (source_code, LIT_MAGIC_STRING__EMPTY)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + } + else + { +#if JERRY_SNAPSHOT_EXEC + if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); + } +#else /* !JERRY_SNAPSHOT_EXEC */ + JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS); +#endif /* JERRY_SNAPSHOT_EXEC */ + + source_code = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + } + + ecma_string_t *result_string_p; + + ECMA_STRING_TO_UTF8_STRING (ecma_get_string_from_value (source_code), source_p, source_size); + result_string_p = ecma_new_ecma_string_from_utf8 (source_p + range_start, range_size); + ECMA_FINALIZE_UTF8_STRING (source_p, source_size); + + return ecma_make_string_value (result_string_p); + } + } + +#if JERRY_SNAPSHOT_EXEC + if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); + } +#else /* !JERRY_SNAPSHOT_EXEC */ + JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS); +#endif /* JERRY_SNAPSHOT_EXEC */ + + lit_magic_string_id_t header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON; + + switch (CBC_FUNCTION_GET_TYPE (bytecode_p->status_flags)) + { + case CBC_FUNCTION_GENERATOR: + { + header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR; + break; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR; + break; + } + case CBC_FUNCTION_ASYNC: + { + header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC; + break; + } + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (ecma_get_magic_string (header_id)); + ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type); + + ecma_stringbuilder_append (&builder, ecma_get_string_from_value (function_arguments)); + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\n) {\n", 5); + ecma_stringbuilder_append (&builder, ecma_get_string_from_value (script_p->source_code)); + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\n}", 2); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +#else /* !JERRY_FUNCTION_TO_STRING */ + return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA); +#endif /* JERRY_FUNCTION_TO_STRING */ +} /* ecma_builtin_function_prototype_object_to_string */ + +/** + * The Function.prototype object's 'apply' routine + * + * See also: + * ECMA-262 v5, 15.3.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, /**< this argument object */ + ecma_value_t arg1, /**< first argument */ + ecma_value_t arg2) /**< second argument */ +{ + /* 2. */ + if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) + { + return ecma_op_function_call (func_obj_p, arg1, NULL, 0); + } + + /* 3. */ + if (!ecma_is_value_object (arg2)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arg2); + + /* 4-5. */ + ecma_length_t length; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + return len_value; + } + + if (length >= ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT) + { + return ecma_raise_range_error (ECMA_ERR_TOO_MANY_ARGUMENTS_DECLARED_FOR_FUNCTION_APPLY); + } + + /* 6. */ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t); + ecma_length_t index = 0; + + /* 7. */ + for (index = 0; index < length; index++) + { + ecma_value_t get_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + ret_value = get_value; + break; + } + + arguments_list_p[index] = get_value; + } + + if (ecma_is_value_empty (ret_value)) + { + JERRY_ASSERT (index == length); + ret_value = ecma_op_function_call (func_obj_p, arg1, arguments_list_p, (uint32_t) length); + } + + for (uint32_t remove_index = 0; remove_index < index; remove_index++) + { + ecma_free_value (arguments_list_p[remove_index]); + } + + JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p); + + return ret_value; +} /* ecma_builtin_function_prototype_object_apply */ + +/** + * The Function.prototype object's 'call' routine + * + * See also: + * ECMA-262 v5, 15.3.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_function_prototype_object_call (ecma_object_t *func_obj_p, /**< this argument object */ + const ecma_value_t *arguments_list_p, /**< list of arguments */ + uint32_t arguments_number) /**< number of arguments */ +{ + if (arguments_number == 0) + { + /* Even a 'this' argument is missing. */ + return ecma_op_function_call (func_obj_p, ECMA_VALUE_UNDEFINED, NULL, 0); + } + + return ecma_op_function_call (func_obj_p, + arguments_list_p[0], + arguments_list_p + 1, + (uint32_t) (arguments_number - 1u)); +} /* ecma_builtin_function_prototype_object_call */ + +/** + * The Function.prototype object's 'bind' routine + * + * See also: + * ECMA-262 v5, 15.3.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p, /**< this argument object */ + const ecma_value_t *arguments_list_p, /**< list of arguments */ + uint32_t arguments_number) /**< number of arguments */ +{ + /* 4. 11. 18. */ + ecma_object_t *prototype_obj_p; + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (this_arg_obj_p)) + { + ecma_value_t proto = ecma_proxy_object_get_prototype_of (this_arg_obj_p); + + if (ECMA_IS_VALUE_ERROR (proto)) + { + return proto; + } + prototype_obj_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (this_arg_obj_p); + if (proto_cp != JMEM_CP_NULL) + { + prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (prototype_obj_p); + } + else + { + prototype_obj_p = NULL; + } +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_object_t *function_p; + ecma_bound_function_t *bound_func_p; + + if (arguments_number == 0 || (arguments_number == 1 && !ecma_is_value_integer_number (arguments_list_p[0]))) + { + function_p = ecma_create_object (prototype_obj_p, sizeof (ecma_bound_function_t), ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + /* 8. */ + bound_func_p = (ecma_bound_function_t *) function_p; + ECMA_SET_NON_NULL_POINTER_TAG (bound_func_p->header.u.bound_function.target_function, this_arg_obj_p, 0); + + bound_func_p->header.u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED; + + if (arguments_number != 0) + { + bound_func_p->header.u.bound_function.args_len_or_this = ecma_copy_value_if_not_object (arguments_list_p[0]); + } + } + else + { + JERRY_ASSERT (arguments_number > 0); + + size_t obj_size = sizeof (ecma_bound_function_t) + (arguments_number * sizeof (ecma_value_t)); + + function_p = ecma_create_object (prototype_obj_p, obj_size, ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + /* 8. */ + bound_func_p = (ecma_bound_function_t *) function_p; + ECMA_SET_NON_NULL_POINTER_TAG (bound_func_p->header.u.bound_function.target_function, this_arg_obj_p, 0); + + /* NOTE: This solution provides temporary false data about the object's size + but prevents GC from freeing it until it's not fully initialized. */ + bound_func_p->header.u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED; + ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); + + for (uint32_t i = 0; i < arguments_number; i++) + { + *args_p++ = ecma_copy_value_if_not_object (arguments_list_p[i]); + } + + ecma_value_t args_len_or_this = ecma_make_integer_value ((ecma_integer_value_t) arguments_number); + bound_func_p->header.u.bound_function.args_len_or_this = args_len_or_this; + } + + if (prototype_obj_p != NULL) + { + ecma_deref_object (prototype_obj_p); + } + + bound_func_p->target_length = ecma_make_integer_value (0); + + ecma_string_t *len_string = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (this_arg_obj_p, len_string, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_deref_object (function_p); + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (status)) + { + ecma_free_property_descriptor (&prop_desc); + ecma_value_t len_value = ecma_op_object_get (this_arg_obj_p, len_string); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (function_p); + return len_value; + } + + if (ecma_is_value_number (len_value)) + { + ecma_number_t len_num; + ecma_op_to_integer (len_value, &len_num); + bound_func_p->target_length = ecma_make_number_value (len_num); + } + ecma_free_value (len_value); + } + + /* 12. */ + ecma_value_t name_value = ecma_op_object_get_by_magic_id (this_arg_obj_p, LIT_MAGIC_STRING_NAME); + if (ECMA_IS_VALUE_ERROR (name_value)) + { + ecma_deref_object (function_p); + return name_value; + } + + ecma_string_t *name_p; + + if (ecma_is_value_string (name_value)) + { + name_p = ecma_get_string_from_value (name_value); + } + else + { + ecma_free_value (name_value); + name_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t bound_function_name = ecma_op_function_form_name (name_p, (char*)"bound ", 6); + + ecma_deref_ecma_string (name_p); + + ecma_property_value_t *name_prop_value_p; + name_prop_value_p = ecma_create_named_data_property (function_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + name_prop_value_p->value = bound_function_name; + + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ + + /* 22. */ + return ecma_make_object_value (function_p); +} /* ecma_builtin_function_prototype_object_bind */ + +/** + * Handle calling [[Call]] of built-in Function.prototype object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_prototype_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_function_prototype_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Function.prototype object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_prototype_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_FUNCTION_PROTOTYPE_NOT_A_CONSTRUCTOR); +} /* ecma_builtin_function_prototype_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_function_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (!ecma_op_is_callable (this_arg)) + { + if (JERRY_UNLIKELY (builtin_routine_id == ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE)) + { + return ECMA_VALUE_FALSE; + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION); + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); + + switch (builtin_routine_id) + { + case ECMA_FUNCTION_PROTOTYPE_TO_STRING: + { + return ecma_builtin_function_prototype_object_to_string (func_obj_p); + } + case ECMA_FUNCTION_PROTOTYPE_APPLY: + { + return ecma_builtin_function_prototype_object_apply (func_obj_p, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_FUNCTION_PROTOTYPE_CALL: + { + return ecma_builtin_function_prototype_object_call (func_obj_p, arguments_list_p, arguments_number); + } + case ECMA_FUNCTION_PROTOTYPE_BIND: + { + return ecma_builtin_function_prototype_object_bind (func_obj_p, arguments_list_p, arguments_number); + } + case ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE: + { + return ecma_op_object_has_instance (func_obj_p, arguments_list_p[0]); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_function_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.h new file mode 100644 index 00000000..363681f5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.h @@ -0,0 +1,24 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTIN_FUNCTION_PROTOTYPE_H +#define ECMA_BUILTIN_FUNCTION_PROTOTYPE_H + +#include "ecma-globals.h" + +ecma_value_t +ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, ecma_value_t arg1, ecma_value_t arg2); + +#endif /* !ECMA_BUILTIN_FUNCTION_PROTOTYPE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h new file mode 100644 index 00000000..8bab444f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h @@ -0,0 +1,55 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Function.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.3.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_FUNCTION, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_FUNCTION_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_APPLY, ECMA_FUNCTION_PROTOTYPE_APPLY, 2, 2) +ROUTINE (LIT_MAGIC_STRING_CALL, ECMA_FUNCTION_PROTOTYPE_CALL, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_BIND, ECMA_FUNCTION_PROTOTYPE_BIND, NON_FIXED, 1) + +/** + * ECMA-262 v6.0 19.2.3.6 @@hasInstance + * the property attributes are: { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. + */ +ROUTINE_WITH_FLAGS (LIT_GLOBAL_SYMBOL_HAS_INSTANCE, ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE, 1, 1, 0 /* flags */) +ACCESSOR_BUILTIN_FUNCTION (LIT_MAGIC_STRING_ARGUMENTS, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +ACCESSOR_BUILTIN_FUNCTION (LIT_MAGIC_STRING_CALLER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp new file mode 100644 index 00000000..7c8e1dfd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-conversion.h" +#include "ecma-eval.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-lex-env.h" + +#include "js-parser.h" +#include "lit-magic-strings.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-function.inc.h" +#define BUILTIN_UNDERSCORED_ID function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup function ECMA Function object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Function object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_builtin_function_dispatch_construct (arguments_list_p, arguments_list_len); +} /* ecma_builtin_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Function object + * + * See also: + * ECMA-262 v5, 15.3. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_NO_OPTS); +} /* ecma_builtin_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h new file mode 100644 index 00000000..92e50eda --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Function built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.3.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, object pointer getter) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.cpp new file mode 100644 index 00000000..acb25eec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.cpp @@ -0,0 +1,68 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" +#include "ecma-function-object.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator-function.inc.h" +#define BUILTIN_UNDERSCORED_ID generator_function +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup generatorfunction ECMA GeneratorFunction object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in GeneratorFunction object + * + * @return constructed generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_generator_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_GENERATOR_FUNCTION); +} /* ecma_builtin_generator_function_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in GeneratorFunction object + * + * @return constructed generator function object - if success + * raised error otherwise + */ +ecma_value_t +ecma_builtin_generator_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_generator_function_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_generator_function_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.inc.h new file mode 100644 index 00000000..39416a91 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-function.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %GeneratorFunction% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v6, 25.2.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.2.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_GENERATOR, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.cpp new file mode 100644 index 00000000..da6269de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.cpp @@ -0,0 +1,258 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-defines.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_GENERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT, + ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW, + ECMA_GENERATOR_PROTOTYPE_ROUTINE_RETURN +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID generator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup generatorprototype ECMA Generator.prototype object built-in + * @{ + */ + +/** + * Convert routine type to operation type. + */ +#define ECMA_GENERATOR_ROUTINE_TO_OPERATION(type) \ + ((ecma_iterator_command_type_t) ((type) -ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT)) + +JERRY_STATIC_ASSERT ((ECMA_GENERATOR_ROUTINE_TO_OPERATION (ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT) == ECMA_ITERATOR_NEXT), + convert_ecma_generator_routine_next_to_ecma_iterator_next_failed); + +JERRY_STATIC_ASSERT ((ECMA_GENERATOR_ROUTINE_TO_OPERATION (ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW) == ECMA_ITERATOR_THROW), + convert_ecma_generator_routine_throw_to_ecma_iterator_throw_failed); + +JERRY_STATIC_ASSERT ((ECMA_GENERATOR_ROUTINE_TO_OPERATION (ECMA_GENERATOR_PROTOTYPE_ROUTINE_RETURN) == ECMA_ITERATOR_RETURN), + convert_ecma_generator_routine_return_to_ecma_iterator_return_failed); + +/** + * Helper function for next / return / throw + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_generator_prototype_object_do (vm_executable_object_t *generator_object_p, /**< generator object */ + ecma_value_t arg, /**< argument */ + ecma_iterator_command_type_t resume_mode) /**< resume mode */ +{ + arg = ecma_copy_value (arg); + + while (true) + { + if (generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + if (generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_RUNNING) + { + return ecma_raise_type_error (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION); + } + + ecma_value_t iterator = generator_object_p->iterator; + ecma_value_t next_method = generator_object_p->frame_ctx.stack_top_p[-1]; + + bool done = false; + + generator_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_RUNNING; + ecma_value_t result = ecma_op_iterator_do (resume_mode, iterator, next_method, arg, &done); + ecma_free_value (arg); + generator_object_p->extended_object.u.cls.u2.executable_obj_flags &= (uint8_t) ~ECMA_EXECUTABLE_OBJECT_RUNNING; + + if (ECMA_IS_VALUE_ERROR (result)) + { + arg = result; + } + else if (done) + { + arg = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (resume_mode == ECMA_ITERATOR_THROW) + { + resume_mode = ECMA_ITERATOR_NEXT; + } + } + else + { + return result; + } + + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (generator_object_p); + generator_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (generator_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (generator_object_p->frame_ctx.stack_top_p[-1])); + generator_object_p->frame_ctx.stack_top_p--; + + if (ECMA_IS_VALUE_ERROR (arg)) + { + arg = jcontext_take_exception (); + resume_mode = ECMA_ITERATOR_THROW; + } + } + + if (resume_mode == ECMA_ITERATOR_RETURN) + { + generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + } + else if (resume_mode == ECMA_ITERATOR_THROW) + { + generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + + ecma_value_t value = opfunc_resume_executable_object (generator_object_p, arg); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + bool done; + done = (generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED); + + if (!done) + { + const uint8_t *byte_code_p = generator_object_p->frame_ctx.byte_code_p; + + JERRY_ASSERT (byte_code_p[-2] == CBC_EXT_OPCODE + && (byte_code_p[-1] == CBC_EXT_YIELD || byte_code_p[-1] == CBC_EXT_YIELD_ITERATOR)); + + if (byte_code_p[-1] == CBC_EXT_YIELD_ITERATOR) + { + ecma_value_t iterator = + ecma_op_get_iterator (value, ECMA_VALUE_SYNC_ITERATOR, generator_object_p->frame_ctx.stack_top_p); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + resume_mode = ECMA_ITERATOR_THROW; + arg = jcontext_take_exception (); + continue; + } + + ecma_deref_object (ecma_get_object_from_value (iterator)); + generator_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD; + generator_object_p->iterator = iterator; + + if (generator_object_p->frame_ctx.stack_top_p[0] != ECMA_VALUE_UNDEFINED) + { + ecma_deref_object (ecma_get_object_from_value (generator_object_p->frame_ctx.stack_top_p[0])); + } + + generator_object_p->frame_ctx.stack_top_p++; + arg = ECMA_VALUE_UNDEFINED; + continue; + } + } + + ecma_value_t result = ecma_create_iter_result_object (value, ecma_make_boolean_value (done)); + ecma_fast_free_value (value); + return result; + } +} /* ecma_builtin_generator_prototype_object_do */ + +/** + * Dispatcher of the Generator built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_generator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + vm_executable_object_t *executable_object_p = NULL; + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_GENERATOR)) + { + executable_object_p = (vm_executable_object_t *) object_p; + } + } + + if (executable_object_p == NULL) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_GENERATOR_OBJECT); + } + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_RUNNING) + { + return ecma_raise_type_error (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION); + } + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + if (builtin_routine_id != ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + jcontext_raise_exception (ecma_copy_value (arguments_list_p[0])); + return ECMA_VALUE_ERROR; + } + + return ecma_builtin_generator_prototype_object_do (executable_object_p, + arguments_list_p[0], + ECMA_GENERATOR_ROUTINE_TO_OPERATION (builtin_routine_id)); +} /* ecma_builtin_generator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h new file mode 100644 index 00000000..07086dbd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Generator.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 25.3.1.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_GENERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_GENERATOR, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_GENERATOR_PROTOTYPE_ROUTINE_NEXT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RETURN, ECMA_GENERATOR_PROTOTYPE_ROUTINE_RETURN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_THROW, ECMA_GENERATOR_PROTOTYPE_ROUTINE_THROW, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.cpp new file mode 100644 index 00000000..6d822933 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.cpp @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator.inc.h" +#define BUILTIN_UNDERSCORED_ID generator +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup generator ECMA Generator object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.inc.h new file mode 100644 index 00000000..b45bd937 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-generator.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %Generator% built-in description (GeneratorFunction.prototype) + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ECMA-262 v6, 25.3.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_GENERATOR_FUNCTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 25.3.2.3.3 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp new file mode 100644 index 00000000..d9ccc8ff --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp @@ -0,0 +1,700 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-eval.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "jrt-bit-fields.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" +#include "lit-strings.h" +#include "vm.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_GLOBAL_ROUTINE_START = 0, + /* Note: these 5 routine ids must be in this order */ + ECMA_GLOBAL_IS_NAN, + ECMA_GLOBAL_IS_FINITE, + ECMA_GLOBAL_EVAL, + ECMA_GLOBAL_PARSE_INT, + ECMA_GLOBAL_PARSE_FLOAT, + ECMA_GLOBAL_DECODE_URI, + ECMA_GLOBAL_DECODE_URI_COMPONENT, + ECMA_GLOBAL_ENCODE_URI, + ECMA_GLOBAL_ENCODE_URI_COMPONENT, + ECMA_GLOBAL_ESCAPE, + ECMA_GLOBAL_UNESCAPE, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-global.inc.h" +#define BUILTIN_UNDERSCORED_ID global +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup global ECMA Global object built-in + * @{ + */ + +/** + * The Global object's 'eval' routine + * + * See also: + * ECMA-262 v5, 15.1.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_eval (ecma_value_t x) /**< routine's first argument */ +{ + if (JERRY_UNLIKELY (!ecma_is_value_string (x))) + { + /* step 1 */ + return ecma_copy_value (x); + } + + uint32_t parse_opts = vm_is_direct_eval_form_call () ? ECMA_PARSE_DIRECT_EVAL : ECMA_PARSE_NO_OPTS; + + /* See also: ECMA-262 v5, 10.1.1 */ + if (parse_opts && vm_is_strict_mode ()) + { + JERRY_ASSERT (parse_opts & ECMA_PARSE_DIRECT_EVAL); + parse_opts |= ECMA_PARSE_STRICT_MODE; + } + + if (vm_is_direct_eval_form_call ()) + { + parse_opts |= ECMA_GET_LOCAL_PARSE_OPTS (); + } + + /* steps 2 to 8 */ + return ecma_op_eval (x, parse_opts); +} /* ecma_builtin_global_object_eval */ + +/** + * The Global object's 'isNaN' routine + * + * See also: + * ECMA-262 v5, 15.1.2.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_is_nan (ecma_number_t arg_num) /**< routine's first argument */ +{ + return ecma_make_boolean_value (ecma_number_is_nan (arg_num)); +} /* ecma_builtin_global_object_is_nan */ + +/** + * The Global object's 'isFinite' routine + * + * See also: + * ECMA-262 v5, 15.1.2.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_is_finite (ecma_number_t arg_num) /**< routine's first argument */ +{ + bool is_finite = !(ecma_number_is_nan (arg_num) || ecma_number_is_infinity (arg_num)); + + return ecma_make_boolean_value (is_finite); +} /* ecma_builtin_global_object_is_finite */ + +/** + * Helper function to check whether a character is in a character bitset. + * + * @return true if the character is in the character bitset. + */ +static bool +ecma_builtin_global_object_character_is_in (uint32_t character, /**< character */ + const uint8_t *bitset) /**< character set */ +{ + JERRY_ASSERT (character < 128); + return (bitset[character >> 3] & (1u << (character & 0x7))) != 0; +} /* ecma_builtin_global_object_character_is_in */ + +/** + * Unescaped URI characters bitset: + * One bit for each character between 0 - 127. + * Bit is set if the character is in the unescaped URI set. + */ +static const uint8_t unescaped_uri_set[16] = { 0x0, 0x0, 0x0, 0x0, 0xda, 0xff, 0xff, 0xaf, + 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 }; + +/** + * Unescaped URI component characters bitset: + * One bit for each character between 0 - 127. + * Bit is set if the character is in the unescaped component URI set. + */ +static const uint8_t unescaped_uri_component_set[16] = { 0x0, 0x0, 0x0, 0x0, 0x82, 0x67, 0xff, 0x3, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 }; + +/** + * Format is a percent sign followed by two hex digits. + */ +#define URI_ENCODED_BYTE_SIZE (3) + +/** + * The Global object's 'decodeURI' and 'decodeURIComponent' routines + * + * See also: + * ECMA-262 v5, 15.1.3.1 + * ECMA-262 v5, 15.1.3.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_decode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size, /**< routine's first argument's + * string buffer's size */ + const uint8_t *reserved_uri_bitset) /**< reserved characters bitset */ +{ + lit_utf8_byte_t *input_char_p = input_start_p; + lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + while (input_char_p < input_end_p) + { + if (*input_char_p != '%') + { + ecma_stringbuilder_append_byte (&builder, *input_char_p++); + continue; + } + + uint32_t hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); + if (hex_value == UINT32_MAX) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_HEXADECIMAL_VALUE); + } + + ecma_char_t decoded_byte = (ecma_char_t) hex_value; + input_char_p += URI_ENCODED_BYTE_SIZE; + + if (decoded_byte <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (ecma_builtin_global_object_character_is_in (decoded_byte, reserved_uri_bitset) + && !ecma_builtin_global_object_character_is_in (decoded_byte, unescaped_uri_component_set)) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_PERCENT); + input_char_p -= 2; + } + else + { + ecma_stringbuilder_append_byte (&builder, (lit_utf8_byte_t) decoded_byte); + } + } + else + { + uint32_t bytes_count; + + if ((decoded_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + bytes_count = 2; + } + else if ((decoded_byte & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + bytes_count = 3; + } + else if ((decoded_byte & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) + { + bytes_count = 4; + } + else + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_UTF8_CHARACTER); + } + + lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; + octets[0] = (lit_utf8_byte_t) decoded_byte; + bool is_valid = true; + + for (uint32_t i = 1; i < bytes_count; i++) + { + if (input_char_p >= input_end_p || *input_char_p != '%') + { + is_valid = false; + break; + } + else + { + hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); + + if (hex_value == UINT32_MAX || (hex_value & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + is_valid = false; + break; + } + + input_char_p += URI_ENCODED_BYTE_SIZE; + octets[i] = (lit_utf8_byte_t) hex_value; + } + } + + if (!is_valid || !lit_is_valid_utf8_string (octets, bytes_count, true)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_UTF8_STRING); + } + + lit_code_point_t cp; + lit_read_code_point_from_utf8 (octets, bytes_count, &cp); + + if (lit_is_code_point_utf16_high_surrogate (cp) || lit_is_code_point_utf16_low_surrogate (cp)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_INVALID_UTF8_CODEPOINT); + } + + lit_utf8_byte_t result_chars[LIT_CESU8_MAX_BYTES_IN_CODE_POINT]; + lit_utf8_size_t cp_size = lit_code_point_to_cesu8 (cp, result_chars); + ecma_stringbuilder_append_raw (&builder, result_chars, cp_size); + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_decode_uri_helper */ + +/** + * Helper function to encode byte as hexadecimal values. + */ +static void +ecma_builtin_global_object_byte_to_hex (lit_utf8_byte_t *dest_p, /**< destination pointer */ + uint32_t byte) /**< value */ +{ + JERRY_ASSERT (byte < 256); + + dest_p[0] = LIT_CHAR_PERCENT; + ecma_char_t hex_digit = (ecma_char_t) (byte >> 4); + dest_p[1] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); + hex_digit = (lit_utf8_byte_t) (byte & 0xf); + dest_p[2] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); +} /* ecma_builtin_global_object_byte_to_hex */ + +/** + * The Global object's 'encodeURI' and 'encodeURIComponent' routines + * + * See also: + * ECMA-262 v5, 15.1.3.3 + * ECMA-262 v5, 15.1.3.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_encode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size, /**< routine's first argument's + * string buffer's size */ + const uint8_t *unescaped_uri_bitset_p) /**< unescaped bitset */ +{ + lit_utf8_byte_t *input_char_p = input_start_p; + const lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_char_t ch; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; + memset (octets, LIT_BYTE_NULL, LIT_UTF8_MAX_BYTES_IN_CODE_POINT); + + while (input_char_p < input_end_p) + { + input_char_p += lit_read_code_unit_from_cesu8 (input_char_p, &ch); + + if (lit_is_code_point_utf16_low_surrogate (ch)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING); + } + + lit_code_point_t cp = ch; + + if (lit_is_code_point_utf16_high_surrogate (ch)) + { + if (input_char_p == input_end_p) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING); + } + + ecma_char_t next_ch; + lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (input_char_p, &next_ch); + + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + cp = lit_convert_surrogate_pair_to_code_point (ch, next_ch); + input_char_p += read_size; + } + else + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_uri_error (ECMA_ERR_UNICODE_SURROGATE_PAIR_MISSING); + } + } + + lit_utf8_size_t utf_size = lit_code_point_to_utf8 (cp, octets); + lit_utf8_byte_t result_chars[URI_ENCODED_BYTE_SIZE]; + + if (utf_size == 1) + { + if (ecma_builtin_global_object_character_is_in (octets[0], unescaped_uri_bitset_p)) + { + ecma_stringbuilder_append_byte (&builder, octets[0]); + } + else + { + ecma_builtin_global_object_byte_to_hex (result_chars, octets[0]); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + else + { + for (uint32_t i = 0; i < utf_size; i++) + { + JERRY_ASSERT (utf_size <= LIT_UTF8_MAX_BYTES_IN_CODE_POINT); + ecma_builtin_global_object_byte_to_hex (result_chars, octets[i]); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_encode_uri_helper */ + +#if JERRY_BUILTIN_ANNEXB + +/** + * Maximum value of a byte. + */ +#define ECMA_ESCAPE_MAXIMUM_BYTE_VALUE (255) + +/** + * Format is a percent sign followed by lowercase u and four hex digits. + */ +#define ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE (6) + +/** + * Escape characters bitset: + * One bit for each character between 0 - 127. + * Bit is set if the character does not need to be converted to %xx form. + * These characters are: a-z A-Z 0-9 @ * _ + - . / + */ +static const uint8_t ecma_escape_set[16] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0xec, 0xff, 0x3, + 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x7 }; + +/** + * The Global object's 'escape' routine + * + * See also: + * ECMA-262 v5, B.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_escape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size) /**< routine's first argument's + * string buffer's size */ +{ + const lit_utf8_byte_t *input_curr_p = input_start_p; + const lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + lit_utf8_byte_t result_chars[URI_ENCODED_BYTE_SIZE]; + + while (input_curr_p < input_end_p) + { + ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); + + if (chr <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (ecma_builtin_global_object_character_is_in ((uint32_t) chr, ecma_escape_set)) + { + ecma_stringbuilder_append_char (&builder, chr); + } + else + { + ecma_builtin_global_object_byte_to_hex (result_chars, chr); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + else if (chr > ECMA_ESCAPE_MAXIMUM_BYTE_VALUE) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_PERCENT); + ecma_stringbuilder_append_char (&builder, LIT_CHAR_LOWERCASE_U); + + ecma_builtin_global_object_byte_to_hex (result_chars, (chr >> JERRY_BITSINBYTE)); + ecma_stringbuilder_append_raw (&builder, result_chars + 1, 2); + + ecma_builtin_global_object_byte_to_hex (result_chars, (chr & 0xff)); + ecma_stringbuilder_append_raw (&builder, result_chars + 1, 2); + } + else + { + ecma_builtin_global_object_byte_to_hex (result_chars, chr); + ecma_stringbuilder_append_raw (&builder, result_chars, URI_ENCODED_BYTE_SIZE); + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_escape */ + +/** + * Utility method to resolve character sequences for the 'unescape' method. + * + * Expected formats: %uxxxx or %yy + * + * @return number of characters processed during the escape resolve + */ +static uint8_t +ecma_builtin_global_object_unescape_resolve_escape (const lit_utf8_byte_t *buffer_p, /**< character buffer */ + bool unicode_sequence, /**< true if unescaping unicode sequence */ + ecma_char_t *out_result_p) /**< [out] resolved character */ +{ + JERRY_ASSERT (buffer_p != NULL); + JERRY_ASSERT (out_result_p != NULL); + + ecma_char_t unescaped_chr = 0; + uint8_t sequence_length = unicode_sequence ? 5 : 2; + uint8_t start = unicode_sequence ? 1 : 0; + + for (uint8_t i = start; i < sequence_length; i++) + { + const lit_utf8_byte_t current_char = buffer_p[i]; + + if (!lit_char_is_hex_digit (current_char)) + { + /* This was not an escape sequence, skip processing */ + return 0; + } + + unescaped_chr = (ecma_char_t) ((unescaped_chr << 4) + (ecma_char_t) lit_char_hex_to_int (current_char)); + } + + *out_result_p = unescaped_chr; + + return sequence_length; +} /* ecma_builtin_global_object_unescape_resolve_escape */ + +/** + * The Global object's 'unescape' routine + * + * See also: + * ECMA-262 v5, B.2.2 + * ECMA-262 v11, B.2.1.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_global_object_unescape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t input_size) /**< routine's first argument's + * string buffer's size */ +{ + if (input_size == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + const lit_utf8_byte_t *input_curr_p = input_start_p; + const lit_utf8_byte_t *input_end_p = input_start_p + input_size; + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + while (input_curr_p < input_end_p) + { + ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); + + // potential pattern + if (chr == LIT_CHAR_PERCENT) + { + const lit_utf8_size_t chars_leftover = (lit_utf8_size_t) (input_end_p - input_curr_p); + + // potential unicode sequence + if (chars_leftover >= 5 && input_curr_p[0] == LIT_CHAR_LOWERCASE_U) + { + input_curr_p += ecma_builtin_global_object_unescape_resolve_escape (input_curr_p, true, &chr); + } + // potential two hexa sequence + else if (chars_leftover >= 2) + { + input_curr_p += ecma_builtin_global_object_unescape_resolve_escape (input_curr_p, false, &chr); + } + } + + ecma_stringbuilder_append_char (&builder, chr); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_global_object_unescape */ + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_global_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + ecma_value_t routine_arg_1 = arguments_list_p[0]; + + if (builtin_routine_id == ECMA_GLOBAL_EVAL) + { + return ecma_builtin_global_object_eval (routine_arg_1); + } + + if (builtin_routine_id <= ECMA_GLOBAL_IS_FINITE) + { + ecma_number_t arg_num; + + routine_arg_1 = ecma_op_to_number (routine_arg_1, &arg_num); + + if (!ecma_is_value_empty (routine_arg_1)) + { + return routine_arg_1; + } + + if (builtin_routine_id == ECMA_GLOBAL_IS_NAN) + { + return ecma_builtin_global_object_is_nan (arg_num); + } + + JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_IS_FINITE); + + return ecma_builtin_global_object_is_finite (arg_num); + } + + ecma_string_t *str_p = ecma_op_to_string (routine_arg_1); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value; + + if (builtin_routine_id <= ECMA_GLOBAL_PARSE_FLOAT) + { + ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size); + + if (builtin_routine_id == ECMA_GLOBAL_PARSE_INT) + { + ret_value = ecma_number_parse_int (string_buff, string_buff_size, arguments_list_p[1]); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_PARSE_FLOAT); + ret_value = ecma_number_parse_float (string_buff, string_buff_size); + } + + ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); + ecma_deref_ecma_string (str_p); + return ret_value; + } + + lit_utf8_size_t input_size = ecma_string_get_size (str_p); + + JMEM_DEFINE_LOCAL_ARRAY (input_start_p, input_size + 1, lit_utf8_byte_t); + + ecma_string_to_cesu8_bytes (str_p, input_start_p, input_size); + + input_start_p[input_size] = LIT_BYTE_NULL; + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ANNEXB + case ECMA_GLOBAL_ESCAPE: + { + ret_value = ecma_builtin_global_object_escape (input_start_p, input_size); + break; + } + case ECMA_GLOBAL_UNESCAPE: + { + ret_value = ecma_builtin_global_object_unescape (input_start_p, input_size); + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_GLOBAL_DECODE_URI: + case ECMA_GLOBAL_DECODE_URI_COMPONENT: + { + const uint8_t *uri_set = + (builtin_routine_id == ECMA_GLOBAL_DECODE_URI ? unescaped_uri_set : unescaped_uri_component_set); + + ret_value = ecma_builtin_global_object_decode_uri_helper (input_start_p, input_size, uri_set); + break; + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI + || builtin_routine_id == ECMA_GLOBAL_ENCODE_URI_COMPONENT); + + const uint8_t *uri_set = + (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI ? unescaped_uri_set : unescaped_uri_component_set); + + ret_value = ecma_builtin_global_object_encode_uri_helper (input_start_p, input_size, uri_set); + break; + } + } + + JMEM_FINALIZE_LOCAL_ARRAY (input_start_p); + + ecma_deref_ecma_string (str_p); + return ret_value; +} /* ecma_builtin_global_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h new file mode 100644 index 00000000..dafcdaba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h @@ -0,0 +1,217 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Global built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Simple value properties: + * (property name, simple value, writable, enumerable, configurable) */ + +/* ECMA-262 v5, 15.1.1.3 */ +SIMPLE_VALUE (LIT_MAGIC_STRING_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_PROPERTY_FIXED) + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v5, 15.1.1.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_NAN, ECMA_BUILTIN_NUMBER_NAN, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.1.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_INFINITY_UL, ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY, ECMA_PROPERTY_FIXED) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.1.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_OBJECT_UL, ECMA_BUILTIN_ID_OBJECT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_FUNCTION_UL, ECMA_BUILTIN_ID_FUNCTION, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.3 */ +#if JERRY_BUILTIN_ARRAY +OBJECT_VALUE (LIT_MAGIC_STRING_ARRAY_UL, ECMA_BUILTIN_ID_ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_ARRAY */ + +#if JERRY_BUILTIN_STRING +/* ECMA-262 v5, 15.1.4.4 */ +OBJECT_VALUE (LIT_MAGIC_STRING_STRING_UL, ECMA_BUILTIN_ID_STRING, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_STRING */ + +#if JERRY_BUILTIN_BOOLEAN +/* ECMA-262 v5, 15.1.4.5 */ +OBJECT_VALUE (LIT_MAGIC_STRING_BOOLEAN_UL, ECMA_BUILTIN_ID_BOOLEAN, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#if JERRY_BUILTIN_NUMBER +/* ECMA-262 v5, 15.1.4.6 */ +OBJECT_VALUE (LIT_MAGIC_STRING_NUMBER_UL, ECMA_BUILTIN_ID_NUMBER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_NUMBER */ + +#if JERRY_BUILTIN_DATE +/* ECMA-262 v5, 15.1.4.7 */ +OBJECT_VALUE (LIT_MAGIC_STRING_DATE_UL, ECMA_BUILTIN_ID_DATE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_DATE */ + +#if JERRY_BUILTIN_REGEXP +/* ECMA-262 v5, 15.1.4.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_REGEXP_UL, ECMA_BUILTIN_ID_REGEXP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_REGEXP */ + +/* ECMA-262 v5, 15.1.4.9 */ +OBJECT_VALUE (LIT_MAGIC_STRING_ERROR_UL, ECMA_BUILTIN_ID_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_ERRORS + +/* ECMA-262 v5, 15.1.4.10 */ +OBJECT_VALUE (LIT_MAGIC_STRING_EVAL_ERROR_UL, ECMA_BUILTIN_ID_EVAL_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.11 */ +OBJECT_VALUE (LIT_MAGIC_STRING_RANGE_ERROR_UL, ECMA_BUILTIN_ID_RANGE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.12 */ +OBJECT_VALUE (LIT_MAGIC_STRING_REFERENCE_ERROR_UL, ECMA_BUILTIN_ID_REFERENCE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.13 */ +OBJECT_VALUE (LIT_MAGIC_STRING_SYNTAX_ERROR_UL, ECMA_BUILTIN_ID_SYNTAX_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.14 */ +OBJECT_VALUE (LIT_MAGIC_STRING_TYPE_ERROR_UL, ECMA_BUILTIN_ID_TYPE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.1.4.15 */ +OBJECT_VALUE (LIT_MAGIC_STRING_URI_ERROR_UL, ECMA_BUILTIN_ID_URI_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_ERRORS */ + +#if JERRY_BUILTIN_MATH +/* ECMA-262 v5, 15.1.5.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_MATH_UL, ECMA_BUILTIN_ID_MATH, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REFLECT +/* ECMA-262 v6, 26.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_REFLECT_UL, ECMA_BUILTIN_ID_REFLECT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_REFLECT */ + +#if JERRY_BUILTIN_ATOMICS +/* ECMA-262 v5, 15.1.5.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_ATOMICS_U, ECMA_BUILTIN_ID_ATOMICS, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_ATOMICS */ + +#if JERRY_BUILTIN_TYPEDARRAY +OBJECT_VALUE (LIT_MAGIC_STRING_ARRAY_BUFFER_UL, ECMA_BUILTIN_ID_ARRAYBUFFER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +OBJECT_VALUE (LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, + ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +OBJECT_VALUE (LIT_MAGIC_STRING_INT8_ARRAY_UL, ECMA_BUILTIN_ID_INT8ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT8_ARRAY_UL, ECMA_BUILTIN_ID_UINT8ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_INT16_ARRAY_UL, ECMA_BUILTIN_ID_INT16ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT16_ARRAY_UL, ECMA_BUILTIN_ID_UINT16ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_INT32_ARRAY_UL, ECMA_BUILTIN_ID_INT32ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT32_ARRAY_UL, ECMA_BUILTIN_ID_UINT32ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_FLOAT32_ARRAY_UL, ECMA_BUILTIN_ID_FLOAT32ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_NUMBER_TYPE_FLOAT64 +OBJECT_VALUE (LIT_MAGIC_STRING_FLOAT64_ARRAY_UL, ECMA_BUILTIN_ID_FLOAT64ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +OBJECT_VALUE (LIT_MAGIC_STRING_BIGINT64_ARRAY_UL, ECMA_BUILTIN_ID_BIGINT64ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL, ECMA_BUILTIN_ID_BIGUINT64ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_BIGINT */ + +OBJECT_VALUE (LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL, + ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#if JERRY_BUILTIN_CONTAINER +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_WEAKSET_UL, ECMA_BUILTIN_ID_WEAKSET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_MAP_UL, ECMA_BUILTIN_ID_MAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_SET_UL, ECMA_BUILTIN_ID_SET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_WEAKMAP_UL, ECMA_BUILTIN_ID_WEAKMAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_CONTAINER */ + +#if JERRY_BUILTIN_WEAKREF +OBJECT_VALUE (LIT_MAGIC_STRING_WEAKREF_UL, ECMA_BUILTIN_ID_WEAKREF, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_WEAKREF */ + +OBJECT_VALUE (LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, ECMA_BUILTIN_ID_AGGREGATE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +OBJECT_VALUE (LIT_MAGIC_STRING_PROMISE_UL, ECMA_BUILTIN_ID_PROMISE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 19.4.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_SYMBOL_UL, ECMA_BUILTIN_ID_SYMBOL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_GLOBAL_THIS +/* ECMA-262 v11, 18.1.1 */ +SIMPLE_VALUE (LIT_MAGIC_STRING_GLOBAL_THIS_UL, ECMA_VALUE_GLOBAL_THIS, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ + +#if JERRY_BUILTIN_DATAVIEW +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_DATAVIEW_UL, ECMA_BUILTIN_ID_DATAVIEW, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#if JERRY_BUILTIN_PROXY +/* ECMA-262 v6, 26.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROXY_UL, ECMA_BUILTIN_ID_PROXY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_PROXY */ + +#if JERRY_BUILTIN_BIGINT +/* ECMA-262 v11, 20.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_BIGINT_UL, ECMA_BUILTIN_ID_BIGINT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_BIGINT */ + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +ROUTINE (LIT_MAGIC_STRING_EVAL, ECMA_GLOBAL_EVAL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_NAN, ECMA_GLOBAL_IS_NAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ECMA_GLOBAL_IS_FINITE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DECODE_URI, ECMA_GLOBAL_DECODE_URI, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, ECMA_GLOBAL_DECODE_URI_COMPONENT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENCODE_URI, ECMA_GLOBAL_ENCODE_URI, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, ECMA_GLOBAL_ENCODE_URI_COMPONENT, 1, 1) + +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_FLOAT, LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_INT, LIT_MAGIC_STRING_PARSE_INT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_ESCAPE, ECMA_GLOBAL_ESCAPE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_UNESCAPE, ECMA_GLOBAL_UNESCAPE, 1, 1) +#endif /* JERRY_BUILTIN_ANNEXB */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.cpp new file mode 100644 index 00000000..3a048d22 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.cpp @@ -0,0 +1,60 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-handlers.h" + +#include "ecma-globals.h" +#include "ecma-iterator-object.h" +#include "ecma-promise-object.h" + +static const ecma_builtin_handler_t ecma_native_handlers[] = { +/** @cond doxygen_suppress */ +#define ECMA_NATIVE_HANDLER(id, handler, length) handler, +#include "ecma-builtin-handlers.inc.h" +#undef ECMA_NATIVE_HANDLER + /** @endcond */ +}; + +static const uint8_t ecma_native_handler_lengths[] = { +/** @cond doxygen_suppress */ +#define ECMA_NATIVE_HANDLER(id, handler, length) length, +#include "ecma-builtin-handlers.inc.h" +#undef ECMA_NATIVE_HANDLER + /** @endcond */ +}; + +/** + * Get the native handler of a built-in handler type. + * + * return Function pointer of the handler + */ +ecma_builtin_handler_t +ecma_builtin_handler_get (ecma_native_handler_id_t id) /**< handler id */ +{ + JERRY_ASSERT (id != ECMA_NATIVE_HANDLER_START && id < ECMA_NATIVE_HANDLER__COUNT); + return ecma_native_handlers[id - 1]; +} /* ecma_builtin_handler_get */ + +/** + * Get the initial 'length' value of a built-in handler type. + * + * return 'length' value of the handler + */ +uint8_t +ecma_builtin_handler_get_length (ecma_native_handler_id_t id) /**< handler id */ +{ + JERRY_ASSERT (id != ECMA_NATIVE_HANDLER_START && id < ECMA_NATIVE_HANDLER__COUNT); + return ecma_native_handler_lengths[id - 1]; +} /* ecma_builtin_handler_get_length */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.h new file mode 100644 index 00000000..01434739 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.h @@ -0,0 +1,51 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTIN_HANDLERS_H +#define ECMA_BUILTIN_HANDLERS_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" + +typedef enum +{ + /** @cond doxygen_suppress */ + ECMA_NATIVE_HANDLER_START = 0, +#define ECMA_NATIVE_HANDLER(id, handler, length) id, +#include "ecma-builtin-handlers.inc.h" +#undef ECMA_NATIVE_HANDLER + ECMA_NATIVE_HANDLER__COUNT + /** @endcond */ +} ecma_native_handler_id_t; + +typedef enum +{ + ECMA_NATIVE_HANDLER_FLAGS_NONE = 0, + ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED = (1 << 0), + ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED = (1 << 1), +} ecma_native_handler_flags_t; + +/** + * Shift for Promise helper handler function. + */ +#define ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT 2 + +ecma_builtin_handler_t ecma_builtin_handler_get (ecma_native_handler_id_t id); +uint8_t ecma_builtin_handler_get_length (ecma_native_handler_id_t id); + +#endif /* !ECMA_BUILTIN_HANDLERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.inc.h new file mode 100644 index 00000000..b5b7a60e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-handlers.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_RESOLVE, ecma_promise_resolve_handler, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_REJECT, ecma_promise_reject_handler, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY, ecma_promise_then_finally_cb, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY, ecma_promise_catch_finally_cb, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, ecma_promise_all_or_all_settled_handler_cb, 1) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR, ecma_op_get_capabilities_executor_cb, 2) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP, ecma_async_from_sync_iterator_unwrap_cb, 1) +#if JERRY_BUILTIN_PROXY +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_PROXY_REVOKE, ecma_proxy_revoke_cb, 0) +#endif /* JERRY_BUILTIN_PROXY */ +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_VALUE_THUNK, ecma_value_thunk_helper_cb, 0) +ECMA_NATIVE_HANDLER (ECMA_NATIVE_HANDLER_VALUE_THROWER, ecma_value_thunk_thrower_cb, 0) diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp new file mode 100644 index 00000000..84b2596c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp @@ -0,0 +1,766 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_DATE + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +/** + * Day names + */ +const char* day_names_p[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + +/** + * Month names + */ +const char* month_names_p[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +/** + * Calculate the elapsed days since Unix Epoch + * + * @return elapsed days since Unix Epoch + */ +int32_t +ecma_date_day_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + if (time < 0) + { + time -= ECMA_DATE_MS_PER_DAY - 1; + } + + return (int32_t) (time / ECMA_DATE_MS_PER_DAY); +} /* ecma_date_day_from_time */ + +/** + * Abstract operation: DayFromYear + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return first of day in the given year + */ +static int32_t +ecma_date_day_from_year (int32_t year) /**< year value */ +{ + if (JERRY_LIKELY (year >= 1970)) + { + return (int32_t) (365 * (year - 1970) + ((year - 1969) / 4) - ((year - 1901) / 100) + ((year - 1601) / 400)); + } + + return (int32_t) (365 * (year - 1970) + floor ((year - 1969) / 4.0) - floor ((year - 1901) / 100.0) + + floor ((year - 1601) / 400.0)); +} /* ecma_date_day_from_year */ + +/** + * Abstract operation: DaysInYear + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return number of days in the given year + */ +static int +ecma_date_days_in_year (int32_t year) /**< year */ +{ + if (year % 4 != 0 || (year % 100 == 0 && (year % 400 != 0))) + { + return ECMA_DATE_DAYS_IN_YEAR; + } + + return ECMA_DATE_DAYS_IN_LEAP_YEAR; +} /* ecma_date_days_in_year */ + +/** + * Abstract operation: InLeapYear + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return 1 - if the year is leap + * 0 - otherwise + */ +static int32_t +ecma_date_in_leap_year (int32_t year) /**< time value */ +{ + return ecma_date_days_in_year (year) - ECMA_DATE_DAYS_IN_YEAR; +} /* ecma_date_in_leap_year */ + +/** + * First days of months in normal and leap years + */ +static const uint16_t first_day_in_month[2][12] = { { + 0, + 31, + 59, + 90, + 120, + 151, + 181, + 212, + 243, + 273, + 304, + 334, /* normal year */ + }, + { + 0, + 31, + 60, + 91, + 121, + 152, + 182, + 213, + 244, + 274, + 305, + 335 /* leap year */ + } }; + +/** + * Abstract operation: YearFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.3 + * + * @return year corresponds to the given time + */ +int32_t +ecma_date_year_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t approx = (int32_t) (floor (time / ECMA_DATE_MS_PER_DAY / 365.2425) + 1970); + int64_t year_ms = ecma_date_day_from_year (approx) * ((int64_t) ECMA_DATE_MS_PER_DAY); + + if ((ecma_number_t) year_ms > time) + { + approx--; + } + + if ((ecma_number_t) (year_ms + ecma_date_days_in_year (approx) * ((int64_t) ECMA_DATE_MS_PER_DAY)) <= time) + { + approx++; + } + + return approx; +} /* ecma_date_year_from_time */ + +/** + * Abstract operation: MonthFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.4 + * + * @return month corresponds to the given time + */ +int32_t +ecma_date_month_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t year = ecma_date_year_from_time (time); + int32_t day_within_year = ecma_date_day_from_time (time) - ecma_date_day_from_year (year); + + JERRY_ASSERT (day_within_year >= 0 && day_within_year < ECMA_DATE_DAYS_IN_LEAP_YEAR); + + int32_t in_leap_year = ecma_date_in_leap_year (year); + + for (int i = 1; i < 12; i++) + { + if (day_within_year < first_day_in_month[in_leap_year][i]) + { + return i - 1; + } + } + + return 11; +} /* ecma_date_month_from_time */ + +/** + * Abstract operation: DateFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.4 + * + * @return date corresponds to the given time + */ +int32_t +ecma_date_date_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t year = ecma_date_year_from_time (time); + int32_t day_within_year = ecma_date_day_from_time (time) - ecma_date_day_from_year (year); + + JERRY_ASSERT (day_within_year >= 0 && day_within_year < ECMA_DATE_DAYS_IN_LEAP_YEAR); + + int32_t in_leap_year = ecma_date_in_leap_year (year); + + int32_t month = 11; + + for (int i = 1; i < 12; i++) + { + if (day_within_year < first_day_in_month[in_leap_year][i]) + { + month = i - 1; + break; + } + } + + return day_within_year + 1 - first_day_in_month[in_leap_year][month]; +} /* ecma_date_date_from_time */ + +/** + * Abstract operation: WeekDay + * + * See also: + * ECMA-262 v11, 20.4.1.4 + * + * @return weekday corresponds to the given time + */ +int32_t +ecma_date_week_day (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t day = ecma_date_day_from_time (time); + + int week_day = (day + 4) % 7; + + return week_day >= 0 ? week_day : week_day + 7; +} /* ecma_date_week_day */ + +/** + * Abstract operation: LocalTZA + * + * See also: + * ECMA-262 v11, 20.4.1.7 + * + * @return local time zone adjustment + */ +int32_t +ecma_date_local_time_zone_adjustment (ecma_number_t time) /**< time value */ +{ + return jerry_port_local_tza (time); +} /* ecma_date_local_time_zone_adjustment */ + +/** + * Abstract operation: UTC + * + * See also: + * ECMA-262 v11, 20.4.1.9 + * + * @return UTC time + */ +ecma_number_t +ecma_date_utc (ecma_number_t time) /**< time value */ +{ + return time - jerry_port_local_tza (time); +} /* ecma_date_utc */ + +/** + * Calculate the time component from the given time + * + * @return time component of the given time + */ +int32_t +ecma_date_time_in_day_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + ecma_number_t day = ecma_date_day_from_time (time); + + return (int32_t) (time - (day * ECMA_DATE_MS_PER_DAY)); +} /* ecma_date_time_in_day_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return hours component of the given time + */ +int32_t +ecma_date_hour_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return (int32_t) (time_in_day / ECMA_DATE_MS_PER_HOUR); +} /* ecma_date_hour_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return minutes component of the given time + */ +int32_t +ecma_date_min_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return ((int32_t) (time_in_day / ECMA_DATE_MS_PER_MINUTE)) % ECMA_DATE_MINUTES_PER_HOUR; +} /* ecma_date_min_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return seconds component of the given time + */ +int32_t +ecma_date_sec_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return ((int32_t) (time_in_day / ECMA_DATE_MS_PER_SECOND)) % ECMA_DATE_SECONDS_PER_MINUTE; +} /* ecma_date_sec_from_time */ + +/** + * Abstract operation: HourFromTime + * + * See also: + * ECMA-262 v11, 20.4.1.10 + * + * @return milliseconds component of the given time + */ +int32_t +ecma_date_ms_from_time (ecma_number_t time) /**< time value */ +{ + JERRY_ASSERT (!ecma_number_is_nan (time)); + + int32_t time_in_day = ecma_date_time_in_day_from_time (time); + + return (int32_t) (time_in_day % ECMA_DATE_MS_PER_SECOND); +} /* ecma_date_ms_from_time */ + +/** + * Abstract operation: MakeTime + * + * See also: + * ECMA-262 v11, 20.4.1.11 + * + * @return constructed time in milliseconds + */ +ecma_number_t +ecma_date_make_time (ecma_number_t hour, /**< hour value */ + ecma_number_t min, /**< minute value */ + ecma_number_t sec, /**< second value */ + ecma_number_t ms) /**< millisecond value */ +{ + if (!ecma_number_is_finite (hour) || !ecma_number_is_finite (min) || !ecma_number_is_finite (sec) + || !ecma_number_is_finite (ms)) + { + return ecma_number_make_nan (); + } + + ecma_number_t h = ecma_number_trunc (hour); + ecma_number_t m = ecma_number_trunc (min); + ecma_number_t s = ecma_number_trunc (sec); + ecma_number_t milli = ecma_number_trunc (ms); + + return h * ECMA_DATE_MS_PER_HOUR + m * ECMA_DATE_MS_PER_MINUTE + s * ECMA_DATE_MS_PER_SECOND + milli; +} /* ecma_date_make_time */ + +/** + * Abstract operation: MakeDay + * + * See also: + * ECMA-262 v11, 20.4.1.12 + * + * @return elpased number of days since Unix Epoch + */ +ecma_number_t +ecma_date_make_day (ecma_number_t year, /**< year value */ + ecma_number_t month, /**< month value */ + ecma_number_t date) /**< date value */ +{ + /* 1. */ + if (!ecma_number_is_finite (year) || !ecma_number_is_finite (month) || !ecma_number_is_finite (date) + || fabs (year) > INT32_MAX) + { + return ecma_number_make_nan (); + } + + /* 2., 3., 4. */ + int32_t y = (int32_t) (year); + ecma_number_t m = ecma_number_trunc (month); + ecma_number_t dt = ecma_number_trunc (date); + + /* 5. */ + int32_t ym = y + (int32_t) (floor (m / 12)); + + /* 6. */ + int32_t mn = (int32_t) fmod (m, 12); + + if (mn < 0) + { + mn += 12; + } + + /* 7. */ + ecma_number_t days = (ecma_date_day_from_year (ym) + first_day_in_month[ecma_date_in_leap_year (ym)][mn] + (dt - 1)); + return days * ECMA_DATE_MS_PER_DAY; +} /* ecma_date_make_day */ + +/** + * Abstract operation: MakeTime + * + * See also: + * ECMA-262 v11, 20.4.1.13 + * + * @return elpased number of milliceconds since Unix Epoch + */ +ecma_number_t +ecma_date_make_date (ecma_number_t day, /**< day value */ + ecma_number_t time) /**< time value */ +{ + if (!ecma_number_is_finite (day) || !ecma_number_is_finite (time)) + { + return ecma_number_make_nan (); + } + + return day + time; +} /* ecma_date_make_date */ + +/** + * Abstract operation: TimeClip + * + * See also: + * ECMA-262 v11, 20.4.1.14 + * + * @return elpased number of milliceconds since Unix Epoch + */ +ecma_number_t +ecma_date_time_clip (ecma_number_t time) /**< time value */ +{ + if (!ecma_number_is_finite (time) || fabs (time) > ECMA_DATE_MAX_VALUE) + { + return ecma_number_make_nan (); + } + + return ecma_number_trunc (time); +} /* ecma_date_time_clip */ + +/** + * Common function to convert date to string. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */ + const char *format_p) /**< format buffer */ +{ + const uint32_t date_buffer_length = 37; + JERRY_VLA (lit_utf8_byte_t, date_buffer, date_buffer_length); + + lit_utf8_byte_t *dest_p = date_buffer; + + while (*format_p != LIT_CHAR_NULL) + { + if (*format_p != LIT_CHAR_DOLLAR_SIGN) + { + *dest_p++ = (lit_utf8_byte_t) *format_p++; + continue; + } + + format_p++; + + const char *str_p = NULL; + int32_t number = 0; + int32_t number_length = 0; + + switch (*format_p) + { + case LIT_CHAR_UPPERCASE_Y: /* Year. */ + { + number = ecma_date_year_from_time (datetime_number); + + if (number >= 100000 || number <= -100000) + { + number_length = 6; + } + else if (number >= 10000 || number <= -10000) + { + number_length = 5; + } + else + { + number_length = 4; + } + break; + } + case LIT_CHAR_LOWERCASE_Y: /* ISO Year: -000001, 0000, 0001, 9999, +012345 */ + { + number = ecma_date_year_from_time (datetime_number); + if (0 <= number && number <= 9999) + { + number_length = 4; + } + else + { + number_length = 6; + } + break; + } + case LIT_CHAR_UPPERCASE_M: /* Month. */ + { + int32_t month = ecma_date_month_from_time (datetime_number); + + JERRY_ASSERT (month >= 0 && month <= 11); + + str_p = month_names_p[month]; + break; + } + case LIT_CHAR_UPPERCASE_O: /* Month as number. */ + { + /* The 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a + * number from 0 to 11, but we have to print the month from 1 to 12 + * for ISO 8601 standard (ECMA 262 v5, 15.9.1.15). */ + number = ecma_date_month_from_time (datetime_number) + 1; + number_length = 2; + break; + } + case LIT_CHAR_UPPERCASE_D: /* Day. */ + { + number = ecma_date_date_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_UPPERCASE_W: /* Day of week. */ + { + int32_t day = ecma_date_week_day (datetime_number); + + JERRY_ASSERT (day >= 0 && day <= 6); + + str_p = day_names_p[day]; + break; + } + case LIT_CHAR_LOWERCASE_H: /* Hour. */ + { + number = ecma_date_hour_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_M: /* Minutes. */ + { + number = ecma_date_min_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_S: /* Seconds. */ + { + number = ecma_date_sec_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_I: /* Milliseconds. */ + { + number = ecma_date_ms_from_time (datetime_number); + number_length = 3; + break; + } + case LIT_CHAR_LOWERCASE_Z: /* Time zone hours part. */ + { + int32_t time_zone = ecma_date_local_time_zone_adjustment (datetime_number); + + if (time_zone >= 0) + { + *dest_p++ = LIT_CHAR_PLUS; + } + else + { + *dest_p++ = LIT_CHAR_MINUS; + time_zone = -time_zone; + } + + number = time_zone / ECMA_DATE_MS_PER_HOUR; + number_length = 2; + break; + } + default: + { + JERRY_ASSERT (*format_p == LIT_CHAR_UPPERCASE_Z); /* Time zone minutes part. */ + + int32_t time_zone = ecma_date_local_time_zone_adjustment (datetime_number); + + if (time_zone < 0) + { + time_zone = -time_zone; + } + + number = (time_zone % ECMA_DATE_MS_PER_HOUR) / ECMA_DATE_MS_PER_MINUTE; + number_length = 2; + break; + } + } + + format_p++; + + if (str_p != NULL) + { + /* Print string values: month or day name which is always 3 characters */ + memcpy (dest_p, str_p, 3); + dest_p += 3; + continue; + } + + /* Print right aligned number values. */ + JERRY_ASSERT (number_length > 0); + + if (number < 0) + { + number = -number; + *dest_p++ = '-'; + } + else if (*(format_p - 1) == LIT_CHAR_LOWERCASE_Y && number_length == 6) + { + /* positive sign is compulsory for extended years */ + *dest_p++ = '+'; + } + + dest_p += number_length; + lit_utf8_byte_t *buffer_p = dest_p; + + do + { + buffer_p--; + *buffer_p = (lit_utf8_byte_t) ((number % 10) + (int32_t) LIT_CHAR_0); + number /= 10; + } while (--number_length); + } + + JERRY_ASSERT (dest_p <= date_buffer + date_buffer_length); + + return ecma_make_string_value ( + ecma_new_ecma_string_from_ascii (date_buffer, (lit_utf8_size_t) (dest_p - date_buffer))); +} /* ecma_date_to_string_format */ + +/** + * Common function to create a time zone specific string from a numeric value. + * + * Used by: + * - The Date routine. + * - The Date.prototype.toString routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_date_value_to_string (ecma_number_t datetime_number) /**< datetime */ +{ + datetime_number += ecma_date_local_time_zone_adjustment (datetime_number); + return ecma_date_to_string_format (datetime_number, "$W $M $D $Y $h:$m:$s GMT$z$Z"); +} /* ecma_date_value_to_string */ + +/** + * Common function to create a time zone specific string from a numeric value. + * + * Used by: + * - The Date.prototype.toUTCString routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */ +{ + return ecma_date_to_string_format (datetime_number, "$W, $D $M $Y $h:$m:$s GMT"); +} /* ecma_date_value_to_utc_string */ + +/** + * Common function to create a ISO specific string from a numeric value. + * + * Used by: + * - The Date.prototype.toISOString routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_date_value_to_iso_string (ecma_number_t datetime_number) /** source_array_p [left_idx : right_idx - 1] + * Second -> source_array_p [right_idx : end_idx - 1] + * Output -> output_array_p + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_helper_array_merge_sort_bottom_up (ecma_value_t *source_array_p, /**< arrays to merge */ + uint32_t left_idx, /**< first array begin */ + uint32_t right_idx, /**< first array end */ + uint32_t end_idx, /**< second array end */ + ecma_value_t *output_array_p, /**< output array */ + ecma_value_t compare_func, /**< compare function */ + const ecma_builtin_helper_sort_compare_fn_t sort_cb, /**< sorting cb */ + ecma_object_t *array_buffer_p) /* array_buffer_p */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + uint32_t i = left_idx, j = right_idx; + + for (uint32_t k = left_idx; k < end_idx; k++) + { + ecma_value_t compare_value = ecma_make_number_value (ECMA_NUMBER_ZERO); + + if (i < right_idx && j < end_idx) + { + compare_value = sort_cb (source_array_p[i], source_array_p[j], compare_func, array_buffer_p); + if (ECMA_IS_VALUE_ERROR (compare_value)) + { + ret_value = ECMA_VALUE_ERROR; + break; + } + } + + if (i < right_idx && ecma_get_number_from_value (compare_value) <= ECMA_NUMBER_ZERO) + { + output_array_p[k] = source_array_p[i]; + i++; + } + else + { + output_array_p[k] = source_array_p[j]; + j++; + } + ecma_free_value (compare_value); + } + + return ret_value; +} /* ecma_builtin_helper_array_merge_sort_bottom_up */ + +/** + * Mergesort function + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_array_merge_sort_helper (ecma_value_t *array_p, /**< array to sort */ + uint32_t length, /**< length */ + ecma_value_t compare_func, /**< compare function */ + const ecma_builtin_helper_sort_compare_fn_t sort_cb, /**< sorting cb */ + ecma_object_t *array_buffer_p) /**< arrayBuffer */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + JMEM_DEFINE_LOCAL_ARRAY (dest_array_p, length, ecma_value_t); + + ecma_value_t *temp_p; + ecma_value_t *base_array_p = array_p; + uint32_t r, e; + + for (uint32_t w = 1; w < length; w = 2 * w) + { + for (uint32_t i = 0; i < length; i = i + 2 * w) + { + // End of first array + r = i + w; + if (r > length) + { + r = length; + } + + // End of second array + e = i + 2 * w; + if (e > length) + { + e = length; + } + + // Merge two arrays + ret_value = ecma_builtin_helper_array_merge_sort_bottom_up (array_p, + i, + r, + e, + dest_array_p, + compare_func, + sort_cb, + array_buffer_p); + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + break; + } + } + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + break; + } + + // Swap arrays + temp_p = dest_array_p; + dest_array_p = array_p; + array_p = temp_p; + } + + // Sorted array is in dest_array_p - there was uneven number of arrays swaps + if (dest_array_p == base_array_p) + { + uint32_t index = 0; + temp_p = dest_array_p; + dest_array_p = array_p; + array_p = temp_p; + + while (index < length) + { + array_p[index] = dest_array_p[index]; + index++; + } + JERRY_ASSERT (index == length); + } + + JMEM_FINALIZE_LOCAL_ARRAY (dest_array_p); + + return ret_value; +} /* ecma_builtin_helper_array_merge_sort_helper */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp new file mode 100644 index 00000000..f4916101 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp @@ -0,0 +1,1039 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jmem.h" +#include "lit-char-helpers.h" +#include "lit-magic-strings.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +/** + * Helper function for Object.prototype.toString routine when + * the @@toStringTag property is present + * + * See also: + * ECMA-262 v6, 19.1.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_helper_object_to_string_tag_helper (ecma_value_t tag_value) /**< string tag */ +{ + JERRY_ASSERT (ecma_is_value_string (tag_value)); + + ecma_string_t *tag_str_p = ecma_get_string_from_value (tag_value); + lit_utf8_size_t tag_str_size = ecma_string_get_size (tag_str_p); + ecma_string_t *ret_string_p; + + /* Building string "[object #@@toStringTag#]" + The string size will be size("[object ") + size(#@@toStringTag#) + size ("]"). */ + const lit_utf8_size_t buffer_size = 9 + tag_str_size; + JMEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); + + lit_utf8_byte_t *buffer_ptr = str_buffer; + + const lit_magic_string_id_t magic_string_ids[] = { + LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, + LIT_MAGIC_STRING_OBJECT, + LIT_MAGIC_STRING_SPACE_CHAR, + }; + + /* Copy to buffer the "[object " string */ + for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) + { + buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], + buffer_ptr, + (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); + + JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); + } + + /* Copy to buffer the #@@toStringTag# string */ + ecma_string_to_cesu8_bytes (tag_str_p, buffer_ptr, tag_str_size); + buffer_ptr += tag_str_size; + + JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); + + /* Copy to buffer the "]" string */ + buffer_ptr = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR, + buffer_ptr, + (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); + + JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); + + ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); + + JMEM_FINALIZE_LOCAL_ARRAY (str_buffer); + ecma_deref_ecma_string (tag_str_p); + + return ecma_make_string_value (ret_string_p); +} /* ecma_builtin_helper_object_to_string_tag_helper */ + +/** + * Common implementation of the Object.prototype.toString routine + * + * See also: + * ECMA-262 v5, 15.2.4.2 + * + * Used by: + * - The Object.prototype.toString routine. + * - The Array.prototype.toString routine as fallback. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ + +ecma_value_t +ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ +{ + lit_magic_string_id_t builtin_tag; + + if (ecma_is_value_undefined (this_arg)) + { + builtin_tag = LIT_MAGIC_STRING_UNDEFINED_UL; + } + else if (ecma_is_value_null (this_arg)) + { + builtin_tag = LIT_MAGIC_STRING_NULL_UL; + } + else + { + ecma_value_t obj_this = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (obj_this)) + { + return obj_this; + } + + JERRY_ASSERT (ecma_is_value_object (obj_this)); + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); + + builtin_tag = ecma_object_get_class_name (obj_p); + + ecma_value_t is_array = ecma_is_value_array (obj_this); + + if (ECMA_IS_VALUE_ERROR (is_array)) + { + ecma_deref_object (obj_p); + return is_array; + } + + if (ecma_is_value_true (is_array)) + { + builtin_tag = LIT_MAGIC_STRING_ARRAY_UL; + } + + ecma_value_t tag = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG); + + if (ECMA_IS_VALUE_ERROR (tag)) + { + ecma_deref_object (obj_p); + return tag; + } + + if (ecma_is_value_string (tag)) + { + ecma_deref_object (obj_p); + return ecma_builtin_helper_object_to_string_tag_helper (tag); + } + else if (builtin_tag != LIT_MAGIC_STRING_ARGUMENTS_UL && builtin_tag != LIT_MAGIC_STRING_FUNCTION_UL + && builtin_tag != LIT_MAGIC_STRING_ERROR_UL && builtin_tag != LIT_MAGIC_STRING_BOOLEAN_UL + && builtin_tag != LIT_MAGIC_STRING_NUMBER_UL && builtin_tag != LIT_MAGIC_STRING_STRING_UL + && builtin_tag != LIT_MAGIC_STRING_DATE_UL && builtin_tag != LIT_MAGIC_STRING_REGEXP_UL + && builtin_tag != LIT_MAGIC_STRING_ARRAY_UL) + { + builtin_tag = LIT_MAGIC_STRING_OBJECT_UL; + } + + ecma_free_value (tag); + ecma_deref_object (obj_p); + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + ecma_stringbuilder_append_magic (&builder, LIT_MAGIC_STRING_OBJECT_TO_STRING_UL); + ecma_stringbuilder_append_magic (&builder, builtin_tag); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_RIGHT_SQUARE); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_helper_object_to_string */ + +/** + * The Array.prototype's 'toLocaleString' single element operation routine + * + * See also: + * ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_string_t * +ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< this object */ + ecma_length_t index) /**< array index */ +{ + ecma_value_t index_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t call_value = ecma_op_invoke_by_magic_id (index_value, LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, NULL, 0); + + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return NULL; + } + + ecma_string_t *ret_string_p = ecma_op_to_string (call_value); + + ecma_free_value (call_value); + + return ret_string_p; +} /* ecma_builtin_helper_get_to_locale_string_at_index */ + +/** + * Helper function to normalizing an array index + * + * See also: + * ECMA-262 v5, 15.4.4.10 steps 5, 6, 7 part 2, 8 + * ECMA-262 v5, 15.4.4.12 steps 5, 6 + * + * ECMA-262 v6, 22.1.3.6 steps 5 - 7, 8 part 2, 9, 10 + * ECMA-262 v6, 22.1.3.3 steps 5 - 10, 11 part 2, 12, 13 + * + * Used by: + * - The Array.prototype.slice routine. + * - The Array.prototype.splice routine. + * - The Array.prototype.fill routine. + * - The Array.prototype.copyWithin routine. + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_builtin_helper_array_index_normalize (ecma_value_t arg, /**< index */ + ecma_length_t length, /**< array's length */ + ecma_length_t *number_p) /**< [out] ecma_length_t */ +{ + ecma_number_t to_int; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg, &to_int))) + { + return ECMA_VALUE_ERROR; + } + + *number_p = ((to_int < 0) ? (ecma_length_t) JERRY_MAX (((ecma_number_t) length + to_int), 0) + : (ecma_length_t) JERRY_MIN (to_int, (ecma_number_t) length)); + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_array_index_normalize */ + +/** + * Helper function to normalizing an uint32 index + * + * See also: + * ECMA-262 v5, 15.5.4.13 steps 4 - 7 + * ECMA-262 v6, 22.2.3.5 steps 5 - 10, 11 part 2, 12, 13 + * ECMA-262 v6, 22.2.3.23 steps 5 - 10 + * ECMA-262 v6, 24.1.4.3 steps 6 - 8, 9 part 2, 10, 11 + * ECMA-262 v6, 22.2.3.26 steps 7 - 9, 10 part 2, 11, 12 + * ECMA-262 v6, 22.2.3.8 steps 5 - 7, 8 part 2, 9, 10 + * + * Used by: + * - The String.prototype.slice routine. + * - The Array.prototype.copyWithin routine. + * - The TypedArray.prototype.copyWithin routine. + * - The TypedArray.prototype.slice routine. + * - The ArrayBuffer.prototype.slice routine. + * - The TypedArray.prototype.subarray routine. + * - The TypedArray.prototype.fill routine. + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_builtin_helper_uint32_index_normalize (ecma_value_t arg, /**< index */ + uint32_t length, /**< array's length */ + uint32_t *number_p) /**< [out] uint32_t number */ +{ + ecma_number_t to_int; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg, &to_int))) + { + return ECMA_VALUE_ERROR; + } + + *number_p = ((to_int < 0) ? (uint32_t) JERRY_MAX ((ecma_number_t) length + to_int, 0) + : (uint32_t) JERRY_MIN (to_int, (ecma_number_t) length)); + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_uint32_index_normalize */ + +/** + * Helper function for concatenating an ecma_value_t to an Array. + * + * See also: + * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c + * + * Used by: + * - The Array.prototype.concat routine. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_array_concat_value (ecma_object_t *array_obj_p, /**< array */ + ecma_length_t *length_p, /**< [in,out] array's length */ + ecma_value_t value) /**< value to concat */ +{ + /* 5.b */ + ecma_value_t is_spreadable = ecma_op_is_concat_spreadable (value); + + if (ECMA_IS_VALUE_ERROR (is_spreadable)) + { + return is_spreadable; + } + + bool spread_object = is_spreadable == ECMA_VALUE_TRUE; + /* ES11: 22.1.3.1.5.c.iv.3.b */ + const uint32_t prop_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + if (spread_object) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + ecma_length_t arg_len; + ecma_value_t error = ecma_op_object_get_length (obj_p, &arg_len); + + if (ECMA_IS_VALUE_ERROR (error)) + { + return error; + } + + /* 4 . */ + if ((ecma_number_t) (*length_p + arg_len) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_type_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + /* 5.b.iii */ + for (ecma_length_t array_index = 0; array_index < arg_len; array_index++) + { + /* 5.b.iii.2 */ + ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, array_index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + if (!ecma_is_value_found (get_value)) + { + continue; + } + + /* 5.b.iii.3.b */ + /* This will always be a simple value since 'is_throw' is false, so no need to free. */ + ecma_value_t put_comp = + ecma_builtin_helper_def_prop_by_index (array_obj_p, *length_p + array_index, get_value, prop_flags); + ecma_free_value (get_value); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + return put_comp; + } + } + + *length_p += arg_len; + return ECMA_VALUE_EMPTY; + } + + /* 5.c.i */ + /* This will always be a simple value since 'is_throw' is false, so no need to free. */ + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, (*length_p)++, value, prop_flags); + + if (ECMA_IS_VALUE_ERROR (put_comp)) + { + return put_comp; + } + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_array_concat_value */ + +/** + * Helper function to normalizing a string index + * + * This function clamps the given index to the [0, length] range. + * If the index is negative, 0 value is used. + * If the index is greater than the length of the string, the normalized index will be the length of the string. + * NaN is mapped to zero or length depending on the nan_to_zero parameter. + * + * See also: + * ECMA-262 v5, 15.5.4.15 + * + * Used by: + * - The String.prototype.substring routine. + * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. + * + * @return lit_utf8_size_t - the normalized value of the index + */ +lit_utf8_size_t +ecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */ + lit_utf8_size_t length, /**< string's length */ + bool nan_to_zero) /**< whether NaN is mapped to zero (t) or length (f) */ +{ + uint32_t norm_index = 0; + + if (ecma_number_is_nan (index)) + { + if (!nan_to_zero) + { + norm_index = length; + } + } + else if (!ecma_number_is_negative (index)) + { + if (ecma_number_is_infinity (index)) + { + norm_index = length; + } + else + { + norm_index = ecma_number_to_uint32 (index); + + if (norm_index > length) + { + norm_index = length; + } + } + } + + return norm_index; +} /* ecma_builtin_helper_string_index_normalize */ + +/** + * Helper function for finding lastindex of a search string + * + * This function clamps the given index to the [0, length] range. + * If the index is negative, 0 value is used. + * If the index is greater than the length of the string, the normalized index will be the length of the string. + * + * See also: + * ECMA-262 v6, 21.1.3.9 + * + * Used by: + * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. + * - The ecma_builtin_string_prototype_object_replace_match helper routine. + * + * @return uint32_t - whether there is a match for the search string + */ +static uint32_t +ecma_builtin_helper_string_find_last_index (ecma_string_t *original_str_p, /**< original string */ + ecma_string_t *search_str_p, /**< search string */ + uint32_t position) /**< start_position */ +{ + if (ecma_string_is_empty (search_str_p)) + { + return position; + } + + uint32_t original_length = ecma_string_get_length (original_str_p); + + ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size); + ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size); + + uint32_t ret_value = UINT32_MAX; + + if (original_str_size >= search_str_size) + { + const lit_utf8_byte_t *end_p = original_str_utf8_p + original_str_size; + const lit_utf8_byte_t *current_p = end_p; + + for (ecma_number_t i = original_length; i > position; i--) + { + lit_utf8_decr (¤t_p); + } + + while (current_p + search_str_size > end_p) + { + lit_utf8_decr (¤t_p); + position--; + } + + while (true) + { + if (memcmp (current_p, search_str_utf8_p, search_str_size) == 0) + { + ret_value = position; + break; + } + + if (position == 0) + { + break; + } + + lit_utf8_decr (¤t_p); + position--; + } + } + ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size); + ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size); + + return ret_value; +} /* ecma_builtin_helper_string_find_last_index */ + +/** + * Helper function for string indexOf, lastIndexOf, startsWith, includes, endsWith functions + * + * See also: + * ECMA-262 v5, 15.5.4.7 + * ECMA-262 v5, 15.5.4.8 + * ECMA-262 v6, 21.1.3.6 + * ECMA-262 v6, 21.1.3.7 + * ECMA-262 v6, 21.1.3.18 + * + * Used by: + * - The String.prototype.indexOf routine. + * - The String.prototype.lastIndexOf routine. + * - The String.prototype.startsWith routine. + * - The String.prototype.includes routine. + * - The String.prototype.endsWith routine. + * + * @return ecma_value_t - Returns index (last index) or a + * boolean value + */ +ecma_value_t +ecma_builtin_helper_string_prototype_object_index_of (ecma_string_t *original_str_p, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2, /**< routine's second argument */ + ecma_string_index_of_mode_t mode) /**< routine's mode */ +{ + /* 5 (indexOf) -- 6 (lastIndexOf) */ + const lit_utf8_size_t original_len = ecma_string_get_length (original_str_p); + + /* 4, 6 (startsWith, includes, endsWith) */ + if (mode >= ECMA_STRING_STARTS_WITH) + { + ecma_value_t regexp = ecma_op_is_regexp (arg1); + + if (ECMA_IS_VALUE_ERROR (regexp)) + { + return regexp; + } + + if (regexp == ECMA_VALUE_TRUE) + { + JERRY_ASSERT (ECMA_STRING_LAST_INDEX_OF < mode && mode <= ECMA_STRING_ENDS_WITH); + return ecma_raise_type_error (ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP); + } + } + + /* 7, 8 */ + ecma_string_t *search_str_p = ecma_op_to_string (arg1); + + if (JERRY_UNLIKELY (search_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value; + + /* 4 (indexOf, lastIndexOf), 9 (startsWith, includes), 10 (endsWith) */ + ecma_number_t pos_num; + + if (mode > ECMA_STRING_LAST_INDEX_OF) + { + ret_value = ecma_op_to_integer (arg2, &pos_num); + } + else + { + ret_value = ecma_op_to_number (arg2, &pos_num); + } + + /* 10 (startsWith, includes), 11 (endsWith) */ + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_ecma_string (search_str_p); + return ret_value; + } + + bool use_first_index = mode != ECMA_STRING_LAST_INDEX_OF; + + /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */ + lit_utf8_size_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, use_first_index); + + ecma_number_t ret_num = ECMA_NUMBER_MINUS_ONE; + + ret_value = ECMA_VALUE_FALSE; + + switch (mode) + { + case ECMA_STRING_STARTS_WITH: + { + if (start > original_len) + { + break; + } + /* 15, 16 (startsWith) */ + uint32_t index = ecma_builtin_helper_string_find_index (original_str_p, search_str_p, start); + ret_value = ecma_make_boolean_value (index == start); + break; + } + case ECMA_STRING_INCLUDES: + { + if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, start) != UINT32_MAX) + { + ret_value = ECMA_VALUE_TRUE; + } + break; + } + case ECMA_STRING_ENDS_WITH: + { + if (start == 0) + { + start = original_len; + } + + lit_utf8_size_t search_str_len = ecma_string_get_length (search_str_p); + + if (search_str_len == 0) + { + ret_value = ECMA_VALUE_TRUE; + break; + } + + int32_t start_ends_with = (int32_t) (start - search_str_len); + + if (start_ends_with < 0) + { + break; + } + uint32_t index = ecma_builtin_helper_string_find_index (original_str_p, search_str_p, (uint32_t) start_ends_with); + ret_value = ecma_make_boolean_value (index == (uint32_t) start_ends_with); + break; + } + case ECMA_STRING_INDEX_OF: + { + /* 8 (indexOf) -- 9 (lastIndexOf) */ + ecma_value_t find_index = ecma_builtin_helper_string_find_index (original_str_p, search_str_p, start); + + if (find_index != UINT32_MAX) + { + ret_num = ((ecma_number_t) find_index); + } + ret_value = ecma_make_number_value (ret_num); + break; + } + + case ECMA_STRING_LAST_INDEX_OF: + { + uint32_t index = ecma_builtin_helper_string_find_last_index (original_str_p, search_str_p, start); + + if (index != UINT32_MAX) + { + ret_num = ((ecma_number_t) index); + } + ret_value = ecma_make_number_value (ret_num); + break; + } + + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_deref_ecma_string (search_str_p); + + return ret_value; +} /* ecma_builtin_helper_string_prototype_object_index_of */ + +/** + * Helper function for finding index of a search string + * + * This function clamps the given index to the [0, length] range. + * If the index is negative, 0 value is used. + * If the index is greater than the length of the string, the normalized index will be the length of the string. + * + * See also: + * ECMA-262 v6, 21.1.3.8 + * + * Used by: + * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. + * - The ecma_builtin_string_prototype_object_replace_match helper routine. + * + * @return uint32_t - whether there is a match for the search string + */ +uint32_t +ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, /**< index */ + ecma_string_t *search_str_p, /**< string's length */ + uint32_t start_pos) /**< start position */ +{ + uint32_t match_found = UINT32_MAX; + + if (ecma_string_is_empty (search_str_p)) + { + return start_pos; + } + + ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size); + ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size); + + const lit_utf8_byte_t *str_current_p = original_str_utf8_p; + + for (ecma_number_t i = 0; i < start_pos; i++) + { + lit_utf8_incr (&str_current_p); + } + + const lit_utf8_byte_t *original_end_p = original_str_utf8_p + original_str_size; + + while (!((size_t) (original_end_p - str_current_p) < search_str_size)) + { + if (memcmp (str_current_p, search_str_utf8_p, search_str_size) == 0) + { + match_found = start_pos; + break; + } + + lit_utf8_incr (&str_current_p); + start_pos++; + } + + ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size); + ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size); + + return match_found; +} /* ecma_builtin_helper_string_find_index */ + +/** + * Helper function for using [[DefineOwnProperty]] specialized for indexed property names + * + * Note: this method falls back to the general ecma_builtin_helper_def_prop + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, /**< object */ + ecma_length_t index, /**< property index */ + ecma_value_t value, /**< value */ + uint32_t opts) /**< any combination of ecma_property_flag_t bits */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_builtin_helper_def_prop (obj_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), value, opts); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_builtin_helper_def_prop (obj_p, index_str_p, value, opts); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_builtin_helper_def_prop_by_index */ + +/** + * Helper function for at() functions. + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal 3. 4. 5. 6. + * + * Used by: + * - The Array.prototype.at routine. + * - The String.prototype.at routine. + * - The TypedArray.prototype.at routine. + * + * @return ECMA_VALUE_ERROR - on conversion error + * ECMA_VALUE_UNDEFINED - if the requested index is not exist + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_builtin_helper_calculate_index (ecma_value_t index, /**< relative index argument */ + ecma_length_t length, /**< object's length */ + ecma_length_t *out_index) /**< calculated index */ +{ + JERRY_ASSERT (out_index != NULL); + + ecma_number_t relative_index; + ecma_value_t conversion_result = ecma_op_to_integer (index, &relative_index); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (conversion_result)) + { + return ECMA_VALUE_ERROR; + } + + /* 5. 6. */ + ecma_number_t k; + + if (relative_index >= 0) + { + k = relative_index; + } + else + { + k = ((ecma_number_t) length + relative_index); + } + + /* 7. */ + if (k < 0 || k >= ((ecma_number_t) length)) + { + return ECMA_VALUE_UNDEFINED; + } + + *out_index = (ecma_length_t) k; + + return ECMA_VALUE_EMPTY; +} /* ecma_builtin_helper_calculate_index */ + +/** + * Helper function for using [[DefineOwnProperty]]. + * + * See also: + * ECMA-262 v5, 8.12.9 + * ECMA-262 v5, 15.4.5.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */ + ecma_string_t *name_p, /**< name string */ + ecma_value_t value, /**< value */ + uint32_t opts) /**< any combination of ecma_property_descriptor_status_flags_t bits */ +{ + ecma_property_descriptor_t prop_desc; + + prop_desc.flags = (uint16_t) (ECMA_NAME_DATA_PROPERTY_DESCRIPTOR_BITS | opts); + + prop_desc.value = value; + + return ecma_op_object_define_own_property (obj_p, name_p, &prop_desc); +} /* ecma_builtin_helper_def_prop */ + +/** + * GetSubstitution abstract operation + * + * See: + * ECMA-262 v6.0 21.1.3.14.1 + */ +void +ecma_builtin_replace_substitute (ecma_replace_context_t *ctx_p) /**< replace context */ +{ + JERRY_ASSERT (ctx_p->string_p != NULL); + JERRY_ASSERT (ctx_p->matched_p == NULL + || (ctx_p->matched_p >= ctx_p->string_p && ctx_p->matched_p <= ctx_p->string_p + ctx_p->string_size)); + + lit_utf8_size_t replace_size; + uint8_t replace_flags = ECMA_STRING_FLAG_IS_ASCII; + const lit_utf8_byte_t *replace_buf_p = + ecma_string_get_chars (ctx_p->replace_str_p, &replace_size, NULL, NULL, &replace_flags); + + const lit_utf8_byte_t *const replace_end_p = replace_buf_p + replace_size; + const lit_utf8_byte_t *curr_p = replace_buf_p; + const lit_utf8_byte_t *last_inserted_end_p = replace_buf_p; + + while (curr_p < replace_end_p) + { + if (*curr_p++ == LIT_CHAR_DOLLAR_SIGN) + { + ecma_stringbuilder_append_raw (&(ctx_p->builder), + last_inserted_end_p, + (lit_utf8_size_t) (curr_p - last_inserted_end_p - 1)); + if (curr_p >= replace_end_p) + { + last_inserted_end_p = curr_p - 1; + break; + } + + const lit_utf8_byte_t c = *curr_p++; + + switch (c) + { + case LIT_CHAR_DOLLAR_SIGN: + { + ecma_stringbuilder_append_byte (&(ctx_p->builder), LIT_CHAR_DOLLAR_SIGN); + break; + } + case LIT_CHAR_AMPERSAND: + { + if (JERRY_UNLIKELY (ctx_p->matched_p == NULL)) + { + JERRY_ASSERT (ctx_p->capture_count == 0); + JERRY_ASSERT (ctx_p->u.collection_p != NULL); + JERRY_ASSERT (ctx_p->u.collection_p->item_count > 0); + const ecma_value_t match_value = ctx_p->u.collection_p->buffer_p[0]; + + JERRY_ASSERT (ecma_is_value_string (match_value)); + ecma_stringbuilder_append (&(ctx_p->builder), ecma_get_string_from_value (match_value)); + break; + } + + JERRY_ASSERT (ctx_p->matched_p != NULL); + ecma_stringbuilder_append_raw (&(ctx_p->builder), ctx_p->matched_p, ctx_p->matched_size); + break; + } + case LIT_CHAR_GRAVE_ACCENT: + { + ecma_stringbuilder_append_raw (&(ctx_p->builder), ctx_p->string_p, ctx_p->match_byte_pos); + break; + } + case LIT_CHAR_SINGLE_QUOTE: + { + if (JERRY_UNLIKELY (ctx_p->matched_p == NULL)) + { + JERRY_ASSERT (ctx_p->capture_count == 0); + JERRY_ASSERT (ctx_p->u.collection_p != NULL); + JERRY_ASSERT (ctx_p->u.collection_p->item_count > 0); + const ecma_value_t match_value = ctx_p->u.collection_p->buffer_p[0]; + + JERRY_ASSERT (ecma_is_value_string (match_value)); + const ecma_string_t *const matched_p = ecma_get_string_from_value (match_value); + const lit_utf8_size_t match_size = ecma_string_get_size (matched_p); + const lit_utf8_byte_t *const begin_p = ctx_p->string_p + ctx_p->match_byte_pos + match_size; + + ecma_stringbuilder_append_raw (&(ctx_p->builder), + begin_p, + (lit_utf8_size_t) (ctx_p->string_p + ctx_p->string_size - begin_p)); + break; + } + + JERRY_ASSERT (ctx_p->matched_p != NULL); + ecma_stringbuilder_append_raw (&(ctx_p->builder), + ctx_p->matched_p + ctx_p->matched_size, + ctx_p->string_size - ctx_p->match_byte_pos - ctx_p->matched_size); + break; + } + default: + { + const lit_utf8_byte_t *const number_begin_p = curr_p - 1; + + if (lit_char_is_decimal_digit (c)) + { + uint32_t capture_count = ctx_p->capture_count; + + if (capture_count == 0 && ctx_p->u.collection_p != NULL) + { + capture_count = ctx_p->u.collection_p->item_count; + } + + uint8_t idx = (uint8_t) (c - LIT_CHAR_0); + if (curr_p < replace_end_p && lit_char_is_decimal_digit (*(curr_p))) + { + uint8_t two_digit_index = (uint8_t) (idx * 10 + (uint8_t) (*(curr_p) -LIT_CHAR_0)); + if (two_digit_index < capture_count) + { + idx = two_digit_index; + curr_p++; + } + } + + if (idx > 0 && idx < capture_count) + { + if (ctx_p->capture_count > 0) + { +#if JERRY_BUILTIN_REGEXP + JERRY_ASSERT (ctx_p->u.captures_p != NULL); + const ecma_regexp_capture_t *const capture_p = ctx_p->u.captures_p + idx; + + if (ECMA_RE_IS_CAPTURE_DEFINED (capture_p)) + { + ecma_stringbuilder_append_raw (&(ctx_p->builder), + capture_p->begin_p, + (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p)); + } + + break; +#endif /* JERRY_BUILTIN_REGEXP */ + } + else if (ctx_p->u.collection_p != NULL) + { + const ecma_value_t capture_value = ctx_p->u.collection_p->buffer_p[idx]; + if (!ecma_is_value_undefined (capture_value)) + { + ecma_stringbuilder_append (&(ctx_p->builder), ecma_get_string_from_value (capture_value)); + } + + break; + } + } + } + + ecma_stringbuilder_append_byte (&(ctx_p->builder), LIT_CHAR_DOLLAR_SIGN); + curr_p = number_begin_p; + break; + } + } + + last_inserted_end_p = curr_p; + } + } + + ecma_stringbuilder_append_raw (&(ctx_p->builder), + last_inserted_end_p, + (lit_utf8_size_t) (replace_end_p - last_inserted_end_p)); + + if (replace_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) replace_buf_p, replace_size); + } +} /* ecma_builtin_replace_substitute */ + +/** + * Helper function to determine if method is the builtin exec method + * + * @return true, if function is the builtin exec method + * false, otherwise + */ +bool +ecma_builtin_is_regexp_exec (ecma_extended_object_t *obj_p) /**< function object */ +{ + return (ecma_get_object_type (&obj_p->object) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + && obj_p->u.built_in.routine_id == ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC); +} /* ecma_builtin_is_regexp_exec */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h new file mode 100644 index 00000000..2910e9df --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h @@ -0,0 +1,232 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTIN_HELPERS_H +#define ECMA_BUILTIN_HELPERS_H + +#include "ecma-exceptions.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-regexp-object.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +/** + * List of built-in routine identifiers. + */ +enum +{ + /** These routines must be in this order */ + ECMA_REGEXP_PROTOTYPE_ROUTINE_START = 0, + ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC, +#if JERRY_BUILTIN_ANNEXB + ECMA_REGEXP_PROTOTYPE_ROUTINE_COMPILE, +#endif /* JERRY_BUILTIN_ANNEXB */ + + ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST, + ECMA_REGEXP_PROTOTYPE_ROUTINE_TO_STRING, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_SOURCE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_FLAGS, + + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_IGNORE_CASE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_MULTILINE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_STICKY, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_UNICODE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_DOT_ALL, + + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SEARCH, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT, + ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL, +}; + +/** + * Mode of string index routine. + */ +typedef enum +{ + /** These routines must be in this order */ + ECMA_STRING_LAST_INDEX_OF, /**< String.lastIndexOf: ECMA-262 v5, 15.5.4.8 */ + ECMA_STRING_INDEX_OF, /**< String.indexOf: ECMA-262 v5, 15.5.4.7 */ + ECMA_STRING_STARTS_WITH, /**< String.startsWith: ECMA-262 v6, 21.1.3.18 */ + ECMA_STRING_INCLUDES, /**< String.includes: ECMA-262 v6, 21.1.3.7 */ + ECMA_STRING_ENDS_WITH /**< String.includes: ECMA-262 v6, 21.1.3.6 */ +} ecma_string_index_of_mode_t; + +ecma_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg); +ecma_string_t *ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, ecma_length_t index); +ecma_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, ecma_length_t *length_p, ecma_value_t value); +ecma_value_t ecma_builtin_helper_uint32_index_normalize (ecma_value_t arg, uint32_t length, uint32_t *number_p); +ecma_value_t +ecma_builtin_helper_array_index_normalize (ecma_value_t arg, ecma_length_t length, ecma_length_t *number_p); +ecma_value_t ecma_builtin_helper_string_index_normalize (ecma_number_t index, uint32_t length, bool nan_to_zero); +ecma_value_t ecma_builtin_helper_string_prototype_object_index_of (ecma_string_t *original_str_p, + ecma_value_t arg1, + ecma_value_t arg2, + ecma_string_index_of_mode_t mode); +uint32_t +ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, ecma_string_t *search_str_p, uint32_t start_pos); +ecma_value_t +ecma_builtin_helper_def_prop (ecma_object_t *obj_p, ecma_string_t *name_p, ecma_value_t value, uint32_t opts); + +ecma_value_t +ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, ecma_length_t index, ecma_value_t value, uint32_t opts); +ecma_value_t ecma_builtin_helper_calculate_index (ecma_value_t index, ecma_length_t length, ecma_length_t *out_index); + +/** + * Context for replace substitutions + */ +typedef struct +{ + ecma_stringbuilder_t builder; /**< result string builder */ + const lit_utf8_byte_t *string_p; /**< source string */ + lit_utf8_size_t string_size; /**< source string size */ + const lit_utf8_byte_t *matched_p; /**< matched string */ + lit_utf8_size_t matched_size; /**< matcehd string size */ + lit_utf8_size_t match_byte_pos; /**< byte position of the match in the source string */ + uint16_t flags; /**< replace flags */ + + /** + * Capture results + */ + union + { +#if JERRY_BUILTIN_REGEXP + const ecma_regexp_capture_t *captures_p; /**< array of regexp capturing groups */ +#endif /* JERRY_BUILTIN_REGEXP */ + const ecma_collection_t *collection_p; /**< collection of captured substrings */ + } u; + + uint32_t capture_count; /**< number of captures in the capturing group array */ + ecma_string_t *replace_str_p; /**< replacement string */ +} ecma_replace_context_t; + +void ecma_builtin_replace_substitute (ecma_replace_context_t *ctx_p); +bool ecma_builtin_is_regexp_exec (ecma_extended_object_t *obj_p); + +#if JERRY_BUILTIN_DATE + +/** + * Time range defines for helper functions. + * + * See also: + * ECMA-262 v5, 15.9.1.1, 15.9.1.10 + */ + +/** Hours in a day. */ +#define ECMA_DATE_HOURS_PER_DAY (24) + +/** Minutes in an hour. */ +#define ECMA_DATE_MINUTES_PER_HOUR (60) + +/** Seconds in a minute. */ +#define ECMA_DATE_SECONDS_PER_MINUTE (60) + +/** Milliseconds in a second. */ +#define ECMA_DATE_MS_PER_SECOND (1000) + +/** ECMA_DATE_MS_PER_MINUTE == 60000 */ +#define ECMA_DATE_MS_PER_MINUTE (ECMA_DATE_MS_PER_SECOND * ECMA_DATE_SECONDS_PER_MINUTE) + +/** ECMA_DATE_MS_PER_HOUR == 3600000 */ +#define ECMA_DATE_MS_PER_HOUR (ECMA_DATE_MS_PER_MINUTE * ECMA_DATE_MINUTES_PER_HOUR) + +/** ECMA_DATE_MS_PER_DAY == 86400000 */ +#define ECMA_DATE_MS_PER_DAY ((ECMA_DATE_MS_PER_HOUR * ECMA_DATE_HOURS_PER_DAY)) + +#define ECMA_DATE_DAYS_IN_YEAR (365) + +#define ECMA_DATE_DAYS_IN_LEAP_YEAR (366) + +/** + * This gives a range of 8,640,000,000,000,000 milliseconds + * to either side of 01 January, 1970 UTC. + */ +#define ECMA_DATE_MAX_VALUE 8.64e15 + +/** + * Timezone type. + */ +typedef enum +{ + ECMA_DATE_UTC, /**< date vaule is in UTC */ + ECMA_DATE_LOCAL /**< date vaule is in local time */ +} ecma_date_timezone_t; + +/* ecma-builtin-helpers-date.c */ +extern const char* day_names_p[7]; +extern const char* month_names_p[12]; + +int32_t ecma_date_day_from_time (ecma_number_t time); +int32_t ecma_date_year_from_time (ecma_number_t time); +int32_t ecma_date_month_from_time (ecma_number_t time); +int32_t ecma_date_date_from_time (ecma_number_t time); +int32_t ecma_date_week_day (ecma_number_t time); +int32_t ecma_date_hour_from_time (ecma_number_t time); +int32_t ecma_date_min_from_time (ecma_number_t time); +int32_t ecma_date_sec_from_time (ecma_number_t time); +int32_t ecma_date_ms_from_time (ecma_number_t time); +int32_t ecma_date_time_in_day_from_time (ecma_number_t time); + +int32_t ecma_date_local_time_zone_adjustment (ecma_number_t time); +ecma_number_t ecma_date_utc (ecma_number_t time); +ecma_number_t ecma_date_make_time (ecma_number_t hour, ecma_number_t min, ecma_number_t sec, ecma_number_t ms); +ecma_number_t ecma_date_make_day (ecma_number_t year, ecma_number_t month, ecma_number_t date); +ecma_number_t ecma_date_make_date (ecma_number_t day, ecma_number_t time); +ecma_number_t ecma_date_time_clip (ecma_number_t time); + +ecma_value_t ecma_date_value_to_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_utc_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_iso_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_date_string (ecma_number_t datetime_number); +ecma_value_t ecma_date_value_to_time_string (ecma_number_t datetime_number); + +#endif /* JERRY_BUILTIN_DATE */ + +/* ecma-builtin-helper-error.c */ + +ecma_value_t ecma_builtin_helper_error_dispatch_call (jerry_error_t error_type, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +/* ecma-builtin-helpers-sort.c */ + +/** + * Comparison callback function header for sorting helper routines. + */ +typedef ecma_value_t (*ecma_builtin_helper_sort_compare_fn_t) (ecma_value_t lhs, /**< left value */ + ecma_value_t rhs, /**< right value */ + ecma_value_t compare_func, /**< compare function */ + ecma_object_t *array_buffer_p /**< arrayBuffer */); + +ecma_value_t ecma_builtin_helper_array_merge_sort_helper (ecma_value_t *array_p, + uint32_t length, + ecma_value_t compare_func, + const ecma_builtin_helper_sort_compare_fn_t sort_cb, + ecma_object_t *array_buffer_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_BUILTIN_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h new file mode 100644 index 00000000..3755f612 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h @@ -0,0 +1,241 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BUILTIN_UNDERSCORED_ID +#error "Please, define BUILTIN_UNDERSCORED_ID" +#endif /* !BUILTIN_UNDERSCORED_ID */ + +#ifndef BUILTIN_INC_HEADER_NAME +#error "Please, define BUILTIN_INC_HEADER_NAME" +#endif /* !BUILTIN_INC_HEADER_NAME */ + +#include "ecma-objects.h" + +#define PASTE__(x, y) x##y +#define PASTE_(x, y) PASTE__ (x, y) +#define PASTE(x, y) PASTE_ (x, y) + +#define PROPERTY_DESCRIPTOR_LIST_NAME PASTE (PASTE (ecma_builtin_, BUILTIN_UNDERSCORED_ID), _property_descriptor_list) +#define DISPATCH_ROUTINE_ROUTINE_NAME PASTE (PASTE (ecma_builtin_, BUILTIN_UNDERSCORED_ID), _dispatch_routine) + +#ifndef BUILTIN_CUSTOM_DISPATCH + +#define ROUTINE_ARG(n) , ecma_value_t arg##n +#define ROUTINE_ARG_LIST_0 ecma_value_t this_arg +#define ROUTINE_ARG_LIST_1 ROUTINE_ARG_LIST_0 ROUTINE_ARG (1) +#define ROUTINE_ARG_LIST_2 ROUTINE_ARG_LIST_1 ROUTINE_ARG (2) +#define ROUTINE_ARG_LIST_3 ROUTINE_ARG_LIST_2 ROUTINE_ARG (3) +#define ROUTINE_ARG_LIST_NON_FIXED ROUTINE_ARG_LIST_0, const ecma_value_t *arguments_list_p, uint32_t arguments_list_len +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + static ecma_value_t c_function_name (ROUTINE_ARG_LIST_##args_number); +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + static ecma_value_t c_function_name (ROUTINE_ARG_LIST_##args_number); +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \ + static ecma_value_t c_function_name (ROUTINE_ARG_LIST_##args_number); +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + static ecma_value_t c_getter_func_name (ROUTINE_ARG_LIST_0); \ + static ecma_value_t c_setter_func_name (ROUTINE_ARG_LIST_1); +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + static ecma_value_t c_getter_func_name (ROUTINE_ARG_LIST_0); +#include BUILTIN_INC_HEADER_NAME +#undef ROUTINE_ARG_LIST_NON_FIXED +#undef ROUTINE_ARG_LIST_3 +#undef ROUTINE_ARG_LIST_2 +#undef ROUTINE_ARG_LIST_1 +#undef ROUTINE_ARG_LIST_0 +#undef ROUTINE_ARG + +/** + * List of built-in routine identifiers. + */ +enum +{ + PASTE (ECMA_ROUTINE_START_, BUILTIN_UNDERSCORED_ID) = 0, +#define ROUTINE(name, c_function_name, args_number, length_prop_value) ECMA_ROUTINE_##name##c_function_name, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + ECMA_ROUTINE_##name##c_function_name, +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \ + ECMA_ROUTINE_##name##c_function_name, +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + ECMA_ACCESSOR_##name##c_getter_func_name, ECMA_ACCESSOR_##name##c_setter_func_name, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) ECMA_ACCESSOR_##name##c_getter_func_name, +#include BUILTIN_INC_HEADER_NAME +}; + +#endif /* !BUILTIN_CUSTOM_DISPATCH */ + +/** + * Built-in property list of the built-in object. + */ +const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = { +#ifndef BUILTIN_CUSTOM_DISPATCH +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, \ + ECMA_ROUTINE_VALUE (ECMA_ROUTINE_##name##c_function_name, length_prop_value) }, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, \ + ECMA_ROUTINE_VALUE (ECMA_ROUTINE_##name##c_function_name, length_prop_value) }, +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ROUTINE_VALUE (ECMA_ROUTINE_##name##c_function_name, length_prop_value) }, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_##name##c_getter_func_name }, +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_READ_WRITE (ECMA_ACCESSOR_##name##c_getter_func_name, ECMA_ACCESSOR_##name##c_setter_func_name) }, +#else /* BUILTIN_CUSTOM_DISPATCH */ +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, \ + ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) }, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, \ + ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) }, +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) }, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + c_getter_func_name }, +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_READ_WRITE (c_getter_func_name, c_setter_func_name) }, +#endif /* !BUILTIN_CUSTOM_DISPATCH */ +#define OBJECT_VALUE(name, obj_builtin_id, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_OBJECT, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, obj_builtin_id }, +#define SIMPLE_VALUE(name, simple_value, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_SIMPLE, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, simple_value }, +#define NUMBER_VALUE(name, number_value, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_NUMBER, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, number_value }, +#define STRING_VALUE(name, magic_string_id, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_STRING, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, magic_string_id }, +#define SYMBOL_VALUE(name, symbol) { name, ECMA_BUILTIN_PROPERTY_SYMBOL, ECMA_PROPERTY_BUILT_IN_FIXED, symbol }, +#define INTRINSIC_PROPERTY(name, magic_string_id, prop_attributes) \ + { name, ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY, (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, magic_string_id }, +#define ACCESSOR_BUILTIN_FUNCTION(name, getter_builtin_id, setter_builtin_id, prop_attributes) \ + { name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION, \ + (prop_attributes) | ECMA_PROPERTY_FLAG_BUILT_IN, \ + ECMA_ACCESSOR_READ_WRITE (getter_builtin_id, setter_builtin_id) }, +#include BUILTIN_INC_HEADER_NAME + { LIT_MAGIC_STRING__COUNT, ECMA_BUILTIN_PROPERTY_END, 0, 0 } +}; + +#ifndef BUILTIN_CUSTOM_DISPATCH + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +DISPATCH_ROUTINE_ROUTINE_NAME (uint8_t builtin_routine_id, /**< built-in wide routine + identifier */ + ecma_value_t this_arg_value, /**< 'this' argument + value */ + const ecma_value_t arguments_list[], /**< list of arguments + passed to routine */ + uint32_t arguments_number) /**< length of + * arguments' list */ +{ + /* the arguments may be unused for some built-ins */ + JERRY_UNUSED (this_arg_value); + JERRY_UNUSED (arguments_list); + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { +#define ROUTINE_ARG(n) (arguments_list[n - 1]) +#define ROUTINE_ARG_LIST_0 +#define ROUTINE_ARG_LIST_1 , ROUTINE_ARG (1) +#define ROUTINE_ARG_LIST_2 ROUTINE_ARG_LIST_1, ROUTINE_ARG (2) +#define ROUTINE_ARG_LIST_3 ROUTINE_ARG_LIST_2, ROUTINE_ARG (3) +#define ROUTINE_ARG_LIST_NON_FIXED , arguments_list, arguments_number +#define ROUTINE(name, c_function_name, args_number, length_prop_value) \ + case ECMA_ROUTINE_##name##c_function_name: \ + { \ + return c_function_name (this_arg_value ROUTINE_ARG_LIST_##args_number); \ + } +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + case ECMA_ROUTINE_##name##c_function_name: \ + { \ + return c_function_name (this_arg_value ROUTINE_ARG_LIST_##args_number); \ + } +#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \ + case ECMA_ROUTINE_##name##c_function_name: \ + { \ + return c_function_name (this_arg_value ROUTINE_ARG_LIST_##args_number); \ + } +#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ + case ECMA_ACCESSOR_##name##c_getter_func_name: \ + { \ + return c_getter_func_name (this_arg_value); \ + } \ + case ECMA_ACCESSOR_##name##c_setter_func_name: \ + { \ + return c_setter_func_name (this_arg_value ROUTINE_ARG_LIST_1); \ + } +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + case ECMA_ACCESSOR_##name##c_getter_func_name: \ + { \ + return c_getter_func_name (this_arg_value); \ + } +#include BUILTIN_INC_HEADER_NAME +#undef ROUTINE_ARG +#undef ROUTINE_ARG_LIST_0 +#undef ROUTINE_ARG_LIST_1 +#undef ROUTINE_ARG_LIST_2 +#undef ROUTINE_ARG_LIST_3 +#undef ROUTINE_ARG_LIST_NON_FIXED + + default: + { + JERRY_UNREACHABLE (); + } + } +} /* DISPATCH_ROUTINE_ROUTINE_NAME */ + +#endif /* !BUILTIN_CUSTOM_DISPATCH */ + +#undef BUILTIN_INC_HEADER_NAME +#undef BUILTIN_CUSTOM_DISPATCH +#undef BUILTIN_UNDERSCORED_ID +#undef DISPATCH_ROUTINE_ROUTINE_NAME +#undef ECMA_BUILTIN_PROPERTY_NAME_INDEX +#undef PASTE__ +#undef PASTE_ +#undef PASTE +#undef PROPERTY_DESCRIPTOR_LIST_NAME diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.cpp new file mode 100644 index 00000000..66519dcd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.cpp @@ -0,0 +1,305 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-string-object.h" +#include "ecma-typedarray-object.h" + +#include "lit-char-helpers.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_INTRINSIC_ROUTINE_START = 0, + ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES, + ECMA_INTRINSIC_TYPEDARRAY_PROTOTYPE_VALUES, + ECMA_INTRINSIC_MAP_PROTOTYPE_ENTRIES, + ECMA_INTRINSIC_SET_PROTOTYPE_VALUES, + ECMA_INTRINSIC_ARRAY_TO_STRING, + ECMA_INTRINSIC_DATE_TO_UTC_STRING, + ECMA_INTRINSIC_PARSE_FLOAT, + ECMA_INTRINSIC_PARSE_INT, + ECMA_INTRINSIC_STRING_TRIM_START, + ECMA_INTRINSIC_STRING_TRIM_END, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-intrinsic.inc.h" +#define BUILTIN_UNDERSCORED_ID intrinsic +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup intrinsic ECMA Intrinsic object built-in + * @{ + */ + +/** + * The %ArrayProto_values% intrinsic routine + * + * See also: + * ECMA-262 v5, 15.4.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_intrinsic_array_prototype_values (ecma_value_t this_value) /**< this argument */ +{ + ecma_value_t this_obj = ecma_op_to_object (this_value); + + if (ECMA_IS_VALUE_ERROR (this_obj)) + { + return this_obj; + } + + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_obj); + + ecma_value_t ret_value = ecma_op_create_array_iterator (this_obj_p, ECMA_ITERATOR_VALUES); + + ecma_deref_object (this_obj_p); + + return ret_value; +} /* ecma_builtin_intrinsic_array_prototype_values */ + +/** + * The Map.prototype entries and [@@iterator] routines + * + * See also: + * ECMA-262 v6, 23.1.3.4 + * ECMA-262 v6, 23.1.3.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_intrinsic_map_prototype_entries (ecma_value_t this_value) /**< this value */ +{ + ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_value, LIT_MAGIC_STRING_MAP_UL); + + if (map_object_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + return ecma_op_container_create_iterator (this_value, + ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE, + ECMA_OBJECT_CLASS_MAP_ITERATOR, + ECMA_ITERATOR_ENTRIES); +} /* ecma_builtin_intrinsic_map_prototype_entries */ + +/** + * The Set.prototype values, keys and [@@iterator] routines + * + * See also: + * ECMA-262 v6, 23.2.3.8 + * ECMA-262 v6, 23.2.3.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_intrinsic_set_prototype_values (ecma_value_t this_value) /**< this value */ +{ + ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_value, LIT_MAGIC_STRING_SET_UL); + + if (map_object_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + return ecma_op_container_create_iterator (this_value, + ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE, + ECMA_OBJECT_CLASS_SET_ITERATOR, + ECMA_ITERATOR_VALUES); +} /* ecma_builtin_intrinsic_set_prototype_values */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_intrinsic_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ARRAY + case ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES: + { + return ecma_builtin_intrinsic_array_prototype_values (this_arg); + } + case ECMA_INTRINSIC_ARRAY_TO_STRING: + { + ecma_value_t this_obj = ecma_op_to_object (this_arg); + if (ECMA_IS_VALUE_ERROR (this_obj)) + { + return this_obj; + } + + ecma_value_t result = ecma_array_object_to_string (this_obj); + ecma_deref_object (ecma_get_object_from_value (this_obj)); + + return result; + } +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_INTRINSIC_TYPEDARRAY_PROTOTYPE_VALUES: + { + if (!ecma_is_typedarray (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY); + } + + if (ecma_arraybuffer_is_detached (ecma_typedarray_get_arraybuffer (ecma_get_object_from_value (this_arg)))) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + return ecma_typedarray_iterators_helper (this_arg, ECMA_ITERATOR_VALUES); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_INTRINSIC_SET_PROTOTYPE_VALUES: + { + return ecma_builtin_intrinsic_set_prototype_values (this_arg); + } + case ECMA_INTRINSIC_MAP_PROTOTYPE_ENTRIES: + { + return ecma_builtin_intrinsic_map_prototype_entries (this_arg); + } +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_DATE + case ECMA_INTRINSIC_DATE_TO_UTC_STRING: + { + if (!ecma_is_value_object (this_arg) + || !ecma_object_class_is (ecma_get_object_from_value (this_arg), ECMA_OBJECT_CLASS_DATE)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_DATE_OBJECT); + } + + ecma_number_t *date_value_p = &((ecma_date_object_t *) ecma_get_object_from_value (this_arg))->date_value; + + if (ecma_number_is_nan (*date_value_p)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_INVALID_DATE_UL); + } + + return ecma_date_value_to_utc_string (*date_value_p); + } +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_STRING + case ECMA_INTRINSIC_STRING_TRIM_START: + case ECMA_INTRINSIC_STRING_TRIM_END: + { + if (!ecma_op_require_object_coercible (this_arg)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *to_str_p = ecma_op_to_string (this_arg); + if (to_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ECMA_STRING_TO_UTF8_STRING (to_str_p, start_p, input_start_size); + + lit_utf8_size_t size; + const lit_utf8_byte_t *input_start_p = start_p; + const lit_utf8_byte_t *input_str_end_p = start_p + input_start_size; + + ecma_string_t *ret_str_p; + if (builtin_routine_id == ECMA_INTRINSIC_STRING_TRIM_START) + { + const lit_utf8_byte_t *new_start_p = ecma_string_trim_front (input_start_p, input_str_end_p); + size = (lit_utf8_size_t) (input_str_end_p - new_start_p); + ret_str_p = ecma_new_ecma_string_from_utf8 (new_start_p, size); + } + else + { + const lit_utf8_byte_t *new_end_p = ecma_string_trim_back (input_start_p, input_str_end_p); + size = (lit_utf8_size_t) (new_end_p - input_start_p); + ret_str_p = ecma_new_ecma_string_from_utf8 (input_start_p, size); + } + + ECMA_FINALIZE_UTF8_STRING (start_p, input_start_size); + ecma_value_t result = ecma_make_string_value (ret_str_p); + ecma_deref_ecma_string (to_str_p); + return result; + } +#endif /* JERRY_BUILTIN_STRING */ + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_INTRINSIC_PARSE_INT || builtin_routine_id == ECMA_INTRINSIC_PARSE_FLOAT); + + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result; + ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size); + + if (builtin_routine_id == ECMA_INTRINSIC_PARSE_INT) + { + result = ecma_number_parse_int (string_buff, string_buff_size, arguments_list_p[1]); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_INTRINSIC_PARSE_FLOAT); + result = ecma_number_parse_float (string_buff, string_buff_size); + } + + ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); + ecma_deref_ecma_string (str_p); + return result; + } + } +} /* ecma_builtin_intrinsic_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h new file mode 100644 index 00000000..54c82c4d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Intrinsic built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES, 0, 0) +ROUTINE (LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_TYPEDARRAY_PROTOTYPE_VALUES, 0, 0) +ROUTINE (LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, ECMA_INTRINSIC_SET_PROTOTYPE_VALUES, 0, 0) +ROUTINE (LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, ECMA_INTRINSIC_MAP_PROTOTYPE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM_START, ECMA_INTRINSIC_STRING_TRIM_START, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM_END, ECMA_INTRINSIC_STRING_TRIM_END, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_INTRINSIC_ARRAY_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_UTC_STRING_UL, ECMA_INTRINSIC_DATE_TO_UTC_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_INTRINSIC_PARSE_FLOAT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PARSE_INT, ECMA_INTRINSIC_PARSE_INT, 2, 2) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.cpp new file mode 100644 index 00000000..ca991d66 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.cpp @@ -0,0 +1,102 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_ITERATOR_PROTOTYPE_OBJECT_ITERATOR, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %iteratorprototype% ECMA %IteratorPrototype% object built-in + * @{ + */ + +/** + * The %IteratorPrototype% object's '@@iterator' routine + * + * See also: + * ECMA-262 v6, 22.1.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return the given this value + */ +static ecma_value_t +ecma_builtin_iterator_prototype_object_iterator (ecma_value_t this_val) /**< this argument */ +{ + /* 1. */ + return ecma_copy_value (this_val); +} /* ecma_builtin_iterator_prototype_object_iterator */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< + * list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_ITERATOR_PROTOTYPE_OBJECT_ITERATOR: + { + return ecma_builtin_iterator_prototype_object_iterator (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_iterator_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h new file mode 100644 index 00000000..4054eb40 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %IteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ECMA_BUILTIN_ITERATOR_PROTOTYPE_OBJECT_ITERATOR, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.cpp new file mode 100644 index 00000000..9471a450 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.cpp @@ -0,0 +1,106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-map-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID map_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %mapiteratorprototype% ECMA %MapIteratorPrototype% object built-in + * @{ + */ + +/** + * The %MapIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 23.1.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_map_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + return ecma_op_container_iterator_next (this_val, ECMA_OBJECT_CLASS_MAP_ITERATOR); +} /* ecma_builtin_map_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_map_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_OBJECT_NEXT: + { + return ecma_builtin_map_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_map_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h new file mode 100644 index 00000000..fe2b8187 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h @@ -0,0 +1,32 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %MapIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_MAP_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_BUILTIN_MAP_ITERATOR_PROTOTYPE_ROUTINE_OBJECT_NEXT, 0, 0) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.cpp new file mode 100644 index 00000000..d7a10cc9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.cpp @@ -0,0 +1,66 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-map-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID map_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup map ECMA Map object built-in + * @{ + */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_map_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_MAP_UL); +} /* ecma_builtin_map_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.inc.h new file mode 100644 index 00000000..65d91d69 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map-prototype.inc.h @@ -0,0 +1,55 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Map.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.1.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_MAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.3.13 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_MAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_CLEAR, ECMA_CONTAINER_ROUTINE_CLEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_CONTAINER_ROUTINE_FOREACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET, ECMA_CONTAINER_ROUTINE_GET, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_CONTAINER_ROUTINE_SET, 2, 2) +ROUTINE (LIT_MAGIC_STRING_VALUES, ECMA_CONTAINER_ROUTINE_VALUES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_CONTAINER_ROUTINE_KEYS, 0, 0) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_ENTRIES, + LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.3.10 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_SIZE, ECMA_CONTAINER_ROUTINE_SIZE_GETTER, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.cpp new file mode 100644 index 00000000..817b5f94 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.cpp @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-map.inc.h" +#define BUILTIN_UNDERSCORED_ID map +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup map ECMA Map object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Map object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_map_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_MAP_REQUIRES_NEW); +} /* ecma_builtin_map_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Map object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_map_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_MAP_UL, + ECMA_BUILTIN_ID_MAP_PROTOTYPE); +} /* ecma_builtin_map_dispatch_construct */ + +/** + * 23.1.2.2 get Map [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_map_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_map_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.inc.h new file mode 100644 index 00000000..e1ff9c00 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-map.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Map built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_MAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.1.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_MAP_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 23.1.2.2 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_map_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp new file mode 100644 index 00000000..33a9bc23 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp @@ -0,0 +1,561 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" + +#if defined(_WIN32) +#include +#endif /* defined(_WIN32) */ + +#if JERRY_BUILTIN_MATH + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_MATH_OBJECT_ROUTINE_START = 0, + + ECMA_MATH_OBJECT_ABS, /* ECMA-262 v5, 15.8.2.1 */ + ECMA_MATH_OBJECT_ACOS, /* ECMA-262 v5, 15.8.2.2 */ + ECMA_MATH_OBJECT_ASIN, /* ECMA-262 v5, 15.8.2.3 */ + ECMA_MATH_OBJECT_ATAN, /* ECMA-262 v5, 15.8.2.4 */ + ECMA_MATH_OBJECT_CEIL, /* ECMA-262 v5, 15.8.2.6 */ + ECMA_MATH_OBJECT_COS, /* ECMA-262 v5, 15.8.2.7 */ + ECMA_MATH_OBJECT_EXP, /* ECMA-262 v5, 15.8.2.8 */ + ECMA_MATH_OBJECT_FLOOR, /* ECMA-262 v5, 15.8.2.9 */ + ECMA_MATH_OBJECT_LOG, /* ECMA-262 v5, 15.8.2.10 */ + ECMA_MATH_OBJECT_ROUND, /* ECMA-262 v5, 15.8.2.15 */ + ECMA_MATH_OBJECT_SIN, /* ECMA-262 v5, 15.8.2.16 */ + ECMA_MATH_OBJECT_SQRT, /* ECMA-262 v5, 15.8.2.17 */ + ECMA_MATH_OBJECT_TAN, /* ECMA-262 v5, 15.8.2.18 */ + ECMA_MATH_OBJECT_ACOSH, /* ECMA-262 v6, 20.2.2.3 */ + ECMA_MATH_OBJECT_ASINH, /* ECMA-262 v6, 20.2.2.5 */ + ECMA_MATH_OBJECT_ATANH, /* ECMA-262 v6, 20.2.2.7 */ + ECMA_MATH_OBJECT_CBRT, /* ECMA-262 v6, 20.2.2.9 */ + ECMA_MATH_OBJECT_CLZ32, /* ECMA-262 v6, 20.2.2.11 */ + ECMA_MATH_OBJECT_COSH, /* ECMA-262 v6, 20.2.2.13 */ + ECMA_MATH_OBJECT_EXPM1, /* ECMA-262 v6, 20.2.2.15 */ + ECMA_MATH_OBJECT_FROUND, /* ECMA-262 v6, 20.2.2.17 */ + ECMA_MATH_OBJECT_LOG1P, /* ECMA-262 v6, 20.2.2.21 */ + ECMA_MATH_OBJECT_LOG10, /* ECMA-262 v6, 20.2.2.22 */ + ECMA_MATH_OBJECT_LOG2, /* ECMA-262 v6, 20.2.2.23 */ + ECMA_MATH_OBJECT_SIGN, /* ECMA-262 v6, 20.2.2.29 */ + ECMA_MATH_OBJECT_SINH, /* ECMA-262 v6, 20.2.2.31 */ + ECMA_MATH_OBJECT_TANH, /* ECMA-262 v6, 20.2.2.34 */ + ECMA_MATH_OBJECT_TRUNC, /* ECMA-262 v6, 20.2.2.35 */ + ECMA_MATH_OBJECT_ATAN2, + /* ECMA-262 v5, 15.8.2.5 */ /* first routine with 2 arguments */ + ECMA_MATH_OBJECT_IMUL, /* ECMA-262 v6, 20.2.2.19 */ + ECMA_MATH_OBJECT_POW, + /* ECMA-262 v5, 15.8.2.13 */ /* last routine with 1 or 2 arguments*/ + ECMA_MATH_OBJECT_MAX, /* ECMA-262 v5, 15.8.2.11 */ + ECMA_MATH_OBJECT_MIN, /* ECMA-262 v5, 15.8.2.12 */ + ECMA_MATH_OBJECT_HYPOT, /* ECMA-262 v6, 20.2.2.18 */ + ECMA_MATH_OBJECT_RANDOM, /* ECMA-262 v5, 15.8.2.14 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-math.inc.h" +#define BUILTIN_UNDERSCORED_ID math +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup object ECMA Object object built-in + * @{ + */ + +/** + * The Math object's 'max' 'min' routines. + * + * See also: + * ECMA-262 v5, 15.8.2.11 + * ECMA-262 v5, 15.8.2.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_math_object_max_min (bool is_max, /**< 'max' or 'min' operation */ + const ecma_value_t *arg, /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + ecma_number_t result_num = ecma_number_make_infinity (is_max); + + while (args_number > 0) + { + ecma_number_t arg_num; + ecma_value_t value = ecma_op_to_number (*arg, &arg_num); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + arg++; + args_number--; + + if (ecma_number_is_nan (arg_num)) + { + result_num = arg_num; + } + + if (ecma_number_is_zero (arg_num) && ecma_number_is_zero (result_num)) + { + bool is_negative = ecma_number_is_negative (arg_num); + + if (is_max ? !is_negative : is_negative) + { + result_num = arg_num; + } + } + else + { + if (is_max ? (arg_num > result_num) : (arg_num < result_num)) + { + result_num = arg_num; + } + } + } + + return ecma_make_number_value (result_num); +} /* ecma_builtin_math_object_max_min */ + +/** + * The Math object's 'hypot' routine + * + * See also: + * ECMA-262 v6, 20.2.2.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_math_object_hypot (const ecma_value_t *arg, /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number == 0) + { + return ecma_make_number_value (0.0); + } + + ecma_number_t result_num = 0; + bool inf = false; + + while (args_number > 0) + { + ecma_number_t arg_num; + ecma_value_t value = ecma_op_to_number (*arg, &arg_num); + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + arg++; + args_number--; + + if (ecma_number_is_nan (arg_num) && !inf) + { + result_num = arg_num; + continue; + } + + if (ecma_number_is_infinity (arg_num)) + { + inf = true; + result_num = ecma_number_make_infinity (false); + continue; + } + + result_num += arg_num * arg_num; + } + + return ecma_make_number_value (sqrt (result_num)); +} /* ecma_builtin_math_object_hypot */ + +/** + * The Math object's 'trunc' routine + * + * See also: + * ECMA-262 v6, 20.2.2.35 + * + * @return ecma number + */ +static ecma_number_t +ecma_builtin_math_object_trunc (ecma_number_t arg) +{ + if (ecma_number_is_nan (arg) || ecma_number_is_infinity (arg) || ecma_number_is_zero (arg)) + { + return arg; + } + + if ((arg > 0) && (arg < 1)) + { + return (ecma_number_t) 0.0; + } + + if ((arg < 0) && (arg > -1)) + { + return (ecma_number_t) -0.0; + } + + return (ecma_number_t) arg - fmod (arg, 1); +} /* ecma_builtin_math_object_trunc */ + +/** + * The Math object's 'sign' routine + * + * See also: + * ECMA-262 v6, 20.2.2.29 + * + * @return ecma number + */ +static ecma_number_t +ecma_builtin_math_object_sign (ecma_number_t arg) +{ + if (ecma_number_is_nan (arg) || ecma_number_is_zero (arg)) + { + return arg; + } + + if (ecma_number_is_negative (arg)) + { + return (ecma_number_t) -1.0; + } + + return (ecma_number_t) 1.0; +} /* ecma_builtin_math_object_sign */ + +/** + * The Math object's 'random' routine. + * + * See also: + * ECMA-262 v5, 15.8.2.14 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_math_object_random (void) +{ + const ecma_number_t rand_max = (ecma_number_t) RAND_MAX; + const ecma_number_t rand_max_min_1 = (ecma_number_t) (RAND_MAX - 1); + + return ecma_make_number_value (((ecma_number_t) rand ()) / rand_max * rand_max_min_1 / rand_max); +} /* ecma_builtin_math_object_random */ + +/** + * Dispatcher for the built-in's routines. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_math_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + if (builtin_routine_id <= ECMA_MATH_OBJECT_POW) + { + ecma_number_t x = ecma_number_make_nan (); + ecma_number_t y = ecma_number_make_nan (); + + if (arguments_number >= 1) + { + ecma_value_t value = ecma_op_to_number (arguments_list[0], &x); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + + if (builtin_routine_id >= ECMA_MATH_OBJECT_ATAN2 && arguments_number >= 2) + { + if (ecma_is_value_number (arguments_list[1])) + { + y = ecma_get_number_from_value (arguments_list[1]); + } + else + { + ecma_value_t value = ecma_op_to_number (arguments_list[1], &y); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + } + + switch (builtin_routine_id) + { + case ECMA_MATH_OBJECT_ABS: + { + x = DOUBLE_TO_ECMA_NUMBER_T (fabs (x)); + break; + } + case ECMA_MATH_OBJECT_ACOS: + { + x = DOUBLE_TO_ECMA_NUMBER_T (acos (x)); + break; + } + case ECMA_MATH_OBJECT_ASIN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (asin (x)); + break; + } + case ECMA_MATH_OBJECT_ATAN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (atan (x)); + break; + } + case ECMA_MATH_OBJECT_CEIL: + { + x = DOUBLE_TO_ECMA_NUMBER_T (ceil (x)); + break; + } + case ECMA_MATH_OBJECT_COS: + { + x = DOUBLE_TO_ECMA_NUMBER_T (cos (x)); + break; + } + case ECMA_MATH_OBJECT_EXP: + { + x = DOUBLE_TO_ECMA_NUMBER_T (exp (x)); + break; + } + case ECMA_MATH_OBJECT_FLOOR: + { + x = DOUBLE_TO_ECMA_NUMBER_T (floor (x)); + break; + } + case ECMA_MATH_OBJECT_LOG: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log (x)); + break; + } + case ECMA_MATH_OBJECT_TRUNC: + { + x = ecma_builtin_math_object_trunc (x); + break; + } + case ECMA_MATH_OBJECT_SIGN: + { + x = ecma_builtin_math_object_sign (x); + break; + } + case ECMA_MATH_OBJECT_ROUND: + { + if (ecma_number_is_nan (x) || ecma_number_is_zero (x) || ecma_number_is_infinity (x)) + { + break; + } + + ecma_number_t fraction = fmod (x, ECMA_NUMBER_ONE); + + if (ecma_number_is_zero (fraction)) + { + break; + } + + if (ecma_number_is_negative (x)) + { + if (x >= -ECMA_NUMBER_HALF) + { + x = -ECMA_NUMBER_ZERO; + break; + } + + if (fraction < -ECMA_NUMBER_HALF) + { + x -= ECMA_NUMBER_HALF; + } + } + else if (fraction >= ECMA_NUMBER_HALF) + { + x += ECMA_NUMBER_HALF; + } + + x = ecma_number_trunc (x); + break; + } + case ECMA_MATH_OBJECT_SIN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (sin (x)); + break; + } + case ECMA_MATH_OBJECT_SQRT: + { + x = DOUBLE_TO_ECMA_NUMBER_T (sqrt (x)); + break; + } + case ECMA_MATH_OBJECT_TAN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (tan (x)); + break; + } + case ECMA_MATH_OBJECT_ATAN2: + { + x = DOUBLE_TO_ECMA_NUMBER_T (atan2 (x, y)); + break; + } + case ECMA_MATH_OBJECT_POW: + { + x = ecma_number_pow (x, y); + break; + } + case ECMA_MATH_OBJECT_ACOSH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (acosh (x)); + break; + } + case ECMA_MATH_OBJECT_ASINH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (asinh (x)); + break; + } + case ECMA_MATH_OBJECT_ATANH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (atanh (x)); + break; + } + case ECMA_MATH_OBJECT_CBRT: + { + x = DOUBLE_TO_ECMA_NUMBER_T (cbrt (x)); + break; + } + case ECMA_MATH_OBJECT_COSH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (cosh (x)); + break; + } + case ECMA_MATH_OBJECT_EXPM1: + { + x = DOUBLE_TO_ECMA_NUMBER_T (expm1 (x)); + break; + } + case ECMA_MATH_OBJECT_LOG1P: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log1p (x)); + break; + } + case ECMA_MATH_OBJECT_LOG10: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log10 (x)); + break; + } + case ECMA_MATH_OBJECT_LOG2: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log2 (x)); + break; + } + case ECMA_MATH_OBJECT_SINH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (sinh (x)); + break; + } + case ECMA_MATH_OBJECT_TANH: + { + x = DOUBLE_TO_ECMA_NUMBER_T (tanh (x)); + break; + } + case ECMA_MATH_OBJECT_CLZ32: + { + uint32_t n = ecma_number_to_uint32 (x); +#if defined(__GNUC__) || defined(__clang__) + x = n ? __builtin_clz (n) : 32; +#elif defined(_WIN32) + unsigned long ret; + x = _BitScanReverse (&ret, n) ? 31 - ret : 32; +#else /* !(defined(__GNUC__) || defined(__clang__) || defined(_WIN32)) */ + x = 32; + for (int i = 31; i >= 0; i--) + { + if (n >> i) + { + x = 31 - i; + break; + } + } +#endif /* defined (__GNUC__) || defined (__clang__) */ + break; + } + case ECMA_MATH_OBJECT_FROUND: + { + x = (float) x; + break; + } + case ECMA_MATH_OBJECT_IMUL: + { + x = (int32_t) (ecma_number_to_uint32 (x) * ecma_number_to_uint32 (y)); + break; + } + } + return ecma_make_number_value (x); + } /* if (builtin_routine_id <= ECMA_MATH_OBJECT_POW) */ + + if (builtin_routine_id <= ECMA_MATH_OBJECT_MIN) + { + return ecma_builtin_math_object_max_min (builtin_routine_id == ECMA_MATH_OBJECT_MAX, + arguments_list, + arguments_number); + } + + if (builtin_routine_id == ECMA_MATH_OBJECT_HYPOT) + { + return ecma_builtin_math_object_hypot (arguments_list, arguments_number); + } + + JERRY_ASSERT (builtin_routine_id == ECMA_MATH_OBJECT_RANDOM); + + return ecma_builtin_math_object_random (); +} /* ecma_builtin_math_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_MATH */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h new file mode 100644 index 00000000..c30ad25d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h @@ -0,0 +1,94 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Math built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_MATH + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v5, 15.8.1.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_E_U, ECMA_BUILTIN_NUMBER_E, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LN10_U, ECMA_BUILTIN_NUMBER_LN10, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.3 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LN2_U, ECMA_BUILTIN_NUMBER_LN2, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.4 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LOG2E_U, ECMA_BUILTIN_NUMBER_LOG2E, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.5 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LOG10E_U, ECMA_BUILTIN_NUMBER_LOG10E, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.6 */ +NUMBER_VALUE (LIT_MAGIC_STRING_PI_U, ECMA_BUILTIN_NUMBER_PI, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.7 */ +NUMBER_VALUE (LIT_MAGIC_STRING_SQRT1_2_U, ECMA_BUILTIN_NUMBER_SQRT_1_2, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.8.1.8 */ +NUMBER_VALUE (LIT_MAGIC_STRING_SQRT2_U, ECMA_BUILTIN_NUMBER_SQRT2, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.2.1.9 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_MATH_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_ABS, ECMA_MATH_OBJECT_ABS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ACOS, ECMA_MATH_OBJECT_ACOS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ASIN, ECMA_MATH_OBJECT_ASIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATAN, ECMA_MATH_OBJECT_ATAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATAN2, ECMA_MATH_OBJECT_ATAN2, 2, 2) +ROUTINE (LIT_MAGIC_STRING_CEIL, ECMA_MATH_OBJECT_CEIL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_COS, ECMA_MATH_OBJECT_COS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_EXP, ECMA_MATH_OBJECT_EXP, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FLOOR, ECMA_MATH_OBJECT_FLOOR, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOG, ECMA_MATH_OBJECT_LOG, 1, 1) +ROUTINE (LIT_MAGIC_STRING_MAX, ECMA_MATH_OBJECT_MAX, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_MIN, ECMA_MATH_OBJECT_MIN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_POW, ECMA_MATH_OBJECT_POW, 2, 2) +ROUTINE (LIT_MAGIC_STRING_RANDOM, ECMA_MATH_OBJECT_RANDOM, 0, 0) +ROUTINE (LIT_MAGIC_STRING_ROUND, ECMA_MATH_OBJECT_ROUND, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SIN, ECMA_MATH_OBJECT_SIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SQRT, ECMA_MATH_OBJECT_SQRT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TAN, ECMA_MATH_OBJECT_TAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ACOSH, ECMA_MATH_OBJECT_ACOSH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ASINH, ECMA_MATH_OBJECT_ASINH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATANH, ECMA_MATH_OBJECT_ATANH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CBRT, ECMA_MATH_OBJECT_CBRT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CLZ32, ECMA_MATH_OBJECT_CLZ32, 1, 1) +ROUTINE (LIT_MAGIC_STRING_COSH, ECMA_MATH_OBJECT_COSH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_EXPM1, ECMA_MATH_OBJECT_EXPM1, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FROUND, ECMA_MATH_OBJECT_FROUND, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HYPOT, ECMA_MATH_OBJECT_HYPOT, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_IMUL, ECMA_MATH_OBJECT_IMUL, 2, 2) +ROUTINE (LIT_MAGIC_STRING_LOG1P, ECMA_MATH_OBJECT_LOG1P, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOG10, ECMA_MATH_OBJECT_LOG10, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOG2, ECMA_MATH_OBJECT_LOG2, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SIGN, ECMA_MATH_OBJECT_SIGN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SINH, ECMA_MATH_OBJECT_SINH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TANH, ECMA_MATH_OBJECT_TANH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TRUNC, ECMA_MATH_OBJECT_TRUNC, 1, 1) + +#endif /* JERRY_BUILTIN_MATH */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp new file mode 100644 index 00000000..456f7b64 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp @@ -0,0 +1,673 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_NUMBER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_NUMBER_PROTOTYPE_ROUTINE_START = 0, + ECMA_NUMBER_PROTOTYPE_VALUE_OF, + ECMA_NUMBER_PROTOTYPE_TO_STRING, + ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING, + ECMA_NUMBER_PROTOTYPE_TO_FIXED, + ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL, + ECMA_NUMBER_PROTOTYPE_TO_PRECISION, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-number-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID number_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup numberprototype ECMA Number.prototype object built-in + * @{ + */ + +/** + * Helper for rounding numbers + * + * @return rounded number + */ +static inline lit_utf8_size_t +ecma_builtin_number_prototype_helper_round (lit_utf8_byte_t *digits_p, /**< [in,out] number as a string in decimal + * form */ + lit_utf8_size_t num_digits, /**< length of the string representation */ + int32_t round_num, /**< number of digits to keep */ + int32_t *exponent_p, /**< [in, out] decimal exponent */ + bool zero) /**< true if digits_p represents zero */ +{ + if (round_num == 0 && *exponent_p == 0) + { + if (digits_p[0] >= 5) + { + digits_p[0] = '1'; + } + else + { + digits_p[0] = '0'; + } + + return 1; + } + + if (round_num < 1) + { + return 0; + } + + if ((lit_utf8_size_t) round_num >= num_digits || zero) + { + return num_digits; + } + + if (digits_p[round_num] >= '5') + { + digits_p[round_num] = '0'; + + int i = 1; + + /* Handle carry number. */ + for (; i <= round_num; i++) + { + if (++digits_p[round_num - i] <= '9') + { + break; + } + digits_p[round_num - i] = '0'; + } + + /* Prepend highest digit */ + if (i > round_num) + { + memmove (digits_p + 1, digits_p, num_digits); + digits_p[0] = '1'; + *exponent_p += 1; + } + } + + return (lit_utf8_size_t) round_num; +} /* ecma_builtin_number_prototype_helper_round */ + +/** + * Size of Number toString digit buffers. + */ +#define NUMBER_TO_STRING_MAX_DIGIT_COUNT 64u + +/** + * The Number.prototype object's 'toString' and 'toLocaleString' routines + * + * See also: + * ECMA-262 v5, 15.7.4.2 + * ECMA-262 v5, 15.7.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_prototype_object_to_string (ecma_number_t this_arg_number, /**< this argument number */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + static const lit_utf8_byte_t digit_chars[36] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + uint32_t radix = 10; + if (arguments_list_len > 0 && !ecma_is_value_undefined (arguments_list_p[0])) + { + ecma_number_t arg_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arguments_list_p[0], &arg_num))) + { + return ECMA_VALUE_ERROR; + } + + radix = ecma_number_to_uint32 (arg_num); + + if (radix < 2 || radix > 36) + { + return ecma_raise_range_error (ECMA_ERR_RADIX_IS_OUT_OF_RANGE); + } + } + + if (ecma_number_is_nan (this_arg_number) || ecma_number_is_infinity (this_arg_number) + || ecma_number_is_zero (this_arg_number) || radix == 10) + { + ecma_string_t *ret_str_p = ecma_new_ecma_string_from_number (this_arg_number); + return ecma_make_string_value (ret_str_p); + } + + uint8_t integer_digits[NUMBER_TO_STRING_MAX_DIGIT_COUNT]; + uint8_t fraction_digits[NUMBER_TO_STRING_MAX_DIGIT_COUNT]; + uint32_t integer_zeros = 0; + uint32_t fraction_zeros = 0; + bool is_number_negative = false; + + if (ecma_number_is_negative (this_arg_number)) + { + this_arg_number = -this_arg_number; + is_number_negative = true; + } + + ecma_number_t integer_part = floor (this_arg_number); + ecma_number_t fraction_part = this_arg_number - integer_part; + + uint8_t *integer_cursor_p = integer_digits + NUMBER_TO_STRING_MAX_DIGIT_COUNT; + uint8_t *fraction_cursor_p = fraction_digits; + + if (fraction_part > 0.0) + { + uint8_t digit; + ecma_number_t precision = (ecma_number_get_next (this_arg_number) - this_arg_number) * 0.5f; + precision = JERRY_MAX (precision, ECMA_NUMBER_MIN_VALUE); + + do + { + fraction_part *= radix; + precision *= radix; + + digit = (uint8_t) floor (fraction_part); + + if (digit == 0 && fraction_cursor_p == fraction_digits) + { + fraction_zeros++; + continue; + } + + JERRY_ASSERT (fraction_cursor_p < fraction_digits + NUMBER_TO_STRING_MAX_DIGIT_COUNT); + *fraction_cursor_p++ = digit; + fraction_part -= (ecma_number_t) digit; + } while (fraction_part >= precision); + + /* Round to even */ + if (fraction_part > 0.5 || (fraction_part == 0.5 && (digit & 1) != 0)) + { + /* Add carry and remove overflowing trailing digits */ + while (true) + { + (*(--fraction_cursor_p))++; + + if (*fraction_cursor_p < radix) + { + /* Re-adjust cursor to point after the last significant digit */ + fraction_cursor_p++; + break; + } + + if (fraction_cursor_p == fraction_digits) + { + /* Carry overflowed to integer part */ + integer_part += 1; + break; + } + } + } + + /* Convert fraction digits to characters. */ + for (uint8_t *digit_p = fraction_digits; digit_p < fraction_cursor_p; digit_p++) + { + *digit_p = digit_chars[*digit_p]; + } + } + + while (ecma_number_biased_exp (ecma_number_to_binary (integer_part / radix)) + > ECMA_NUMBER_EXPONENT_BIAS + ECMA_NUMBER_FRACTION_WIDTH) + { + integer_zeros++; + integer_part /= radix; + } + + uint64_t integer_u64 = (uint64_t) integer_part; + + do + { + uint64_t remainder = integer_u64 % radix; + *(--integer_cursor_p) = (uint8_t) digit_chars[remainder]; + + integer_u64 /= radix; + } while (integer_u64 > 0); + + const uint32_t integer_digit_count = + (uint32_t) (integer_digits + NUMBER_TO_STRING_MAX_DIGIT_COUNT - integer_cursor_p); + JERRY_ASSERT (integer_digit_count > 0); + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (is_number_negative) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_MINUS); + } + + ecma_stringbuilder_append_raw (&builder, integer_cursor_p, integer_digit_count); + + while (integer_zeros--) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_0); + } + + if (fraction_cursor_p != fraction_digits) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_DOT); + + while (fraction_zeros--) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_0); + } + + const uint32_t fraction_digit_count = (uint32_t) (fraction_cursor_p - fraction_digits); + JERRY_ASSERT (fraction_digit_count > 0); + + ecma_stringbuilder_append_raw (&builder, fraction_digits, fraction_digit_count); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_number_prototype_object_to_string */ + +/** + * The Number.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v5, 15.7.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_number (this_arg)) + { + return this_arg; + } + else if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_NUMBER)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_number (ext_object_p->u.cls.u3.value)); + + return ext_object_p->u.cls.u3.value; + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_NUMBER); +} /* ecma_builtin_number_prototype_object_value_of */ + +/** + * Type of number routine + */ +typedef enum +{ + NUMBER_ROUTINE_TO_FIXED, /**< Number.prototype.toFixed: ECMA-262 v11, 20.1.3.3 */ + NUMBER_ROUTINE_TO_EXPONENTIAL, /**< Number.prototype.toExponential: ECMA-262 v11, 20.1.3.2 */ + NUMBER_ROUTINE_TO_PRECISION, /**< Number.prototype.toPrecision: ECMA-262 v11, 20.1.3.5 */ + NUMBER_ROUTINE__COUNT, /**< count of the modes */ +} number_routine_mode_t; + +/** + * Helper method to convert a number based on the given routine. + */ +static ecma_value_t +ecma_builtin_number_prototype_object_to_number_convert (ecma_number_t this_num, /**< this argument number */ + ecma_value_t arg, /**< routine's argument */ + number_routine_mode_t mode) /**< number routine mode */ +{ + if (ecma_is_value_undefined (arg) && mode == NUMBER_ROUTINE_TO_PRECISION) + { + return ecma_builtin_number_prototype_object_to_string (this_num, NULL, 0); + } + + ecma_number_t arg_num; + ecma_value_t to_integer = ecma_op_to_integer (arg, &arg_num); + + if (ECMA_IS_VALUE_ERROR (to_integer)) + { + return to_integer; + } + + /* Argument boundary check for toFixed method */ + if (mode == NUMBER_ROUTINE_TO_FIXED && (arg_num <= -1 || arg_num >= 101)) + { + return ecma_raise_range_error (ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE); + } + + /* Handle NaN separately */ + if (ecma_number_is_nan (this_num)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_NAN); + } + + /* Get the parameters of the number */ + lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + lit_utf8_size_t num_of_digits; + int32_t exponent; + int32_t arg_int = ecma_number_to_int32 (arg_num); + bool is_zero = ecma_number_is_zero (this_num); + bool is_negative = ecma_number_is_negative (this_num); + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (is_negative) + { + if (!is_zero) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_MINUS); + } + + this_num *= -1; + } + + /* Handle zero separately */ + if (is_zero) + { + if (mode == NUMBER_ROUTINE_TO_PRECISION) + { + arg_int--; + } + + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + + if (arg_int > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + } + + for (int32_t i = 0; i < arg_int; i++) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + } + + if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL) + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "e+0", 3); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + /* Handle infinity separately */ + if (ecma_number_is_infinity (this_num)) + { + ecma_stringbuilder_append_magic (&builder, LIT_MAGIC_STRING_INFINITY_UL); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + /* Argument boundary check for toExponential and toPrecision methods */ + if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL && (arg_num <= -1 || arg_num >= 101)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_FRACTION_DIGITS_OUT_OF_RANGE); + } + else if (mode == NUMBER_ROUTINE_TO_PRECISION && (arg_num < 1 || arg_num > 100)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_PRECISION_DIGITS_MUST_BE_BETWEEN_IN_RANGE); + } + + num_of_digits = ecma_number_to_decimal (this_num, digits, &exponent); + + /* Handle undefined argument */ + if (ecma_is_value_undefined (arg) && mode == NUMBER_ROUTINE_TO_EXPONENTIAL) + { + arg_int = (int32_t) num_of_digits - 1; + } + + if (mode == NUMBER_ROUTINE_TO_FIXED && exponent > 21) + { + ecma_stringbuilder_destroy (&builder); + + if (is_negative) + { + this_num *= -1; + } + + return ecma_builtin_number_prototype_object_to_string (this_num, NULL, 0); + } + + int32_t digits_to_keep = arg_int; + + if (mode == NUMBER_ROUTINE_TO_FIXED) + { + digits_to_keep += exponent; + } + else if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL) + { + digits_to_keep += 1; + } + + num_of_digits = ecma_builtin_number_prototype_helper_round (digits, num_of_digits, digits_to_keep, &exponent, false); + + /* toExponent routine and toPrecision cases where the exponent > precision or exponent < -5 */ + if (mode == NUMBER_ROUTINE_TO_EXPONENTIAL + || (mode == NUMBER_ROUTINE_TO_PRECISION && (exponent < -5 || exponent > arg_int))) + { + /* Append first digit */ + ecma_stringbuilder_append_byte (&builder, *digits); + + if (mode == NUMBER_ROUTINE_TO_PRECISION) + { + arg_int--; + } + + if (arg_int > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + } + + /* Append significant fraction digits */ + ecma_stringbuilder_append_raw (&builder, digits + 1, num_of_digits - 1); + + /* Append leading zeros */ + for (int32_t i = (int32_t) (num_of_digits); i < arg_int + 1; i++) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + } + + ecma_stringbuilder_append_char (&builder, LIT_CHAR_LOWERCASE_E); + + if (exponent <= 0) + { + exponent = (-exponent) + 1; + ecma_stringbuilder_append_char (&builder, LIT_CHAR_MINUS); + } + else + { + exponent -= 1; + ecma_stringbuilder_append_char (&builder, LIT_CHAR_PLUS); + } + + /* Append exponent part */ + lit_utf8_size_t exp_size = ecma_uint32_to_utf8_string ((uint32_t) exponent, digits, 3); + ecma_stringbuilder_append_raw (&builder, digits, exp_size); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + /* toFixed routine and toPrecision cases where the exponent <= precision and exponent >= -5 */ + lit_utf8_size_t result_digits; + + if (mode == NUMBER_ROUTINE_TO_FIXED) + { + result_digits = ((exponent > 0) ? (lit_utf8_size_t) (exponent + arg_int) : (lit_utf8_size_t) (arg_int + 1)); + } + else + { + result_digits = ((exponent <= 0) ? (lit_utf8_size_t) (1 - exponent + arg_int) : (lit_utf8_size_t) arg_int); + } + + /* Number of digits we copied from digits array */ + lit_utf8_size_t copied_digits = 0; + + if (exponent == 0 && digits_to_keep == 0) + { + ecma_stringbuilder_append_char (&builder, *digits); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + } + + if (exponent <= 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + + if (result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + + /* Append leading zeros to the fraction part */ + for (int32_t i = 0; i < -exponent && result_digits > 0; i++) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + } + } + } + else + { + /* Append significant digits of integer part */ + copied_digits = JERRY_MIN (JERRY_MIN (num_of_digits, result_digits), (lit_utf8_size_t) exponent); + ecma_stringbuilder_append_raw (&builder, digits, copied_digits); + + result_digits -= copied_digits; + num_of_digits -= copied_digits; + exponent -= (int32_t) copied_digits; + + /* Append zeros before decimal point */ + while (exponent > 0 && result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + exponent--; + } + + if (result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_DOT); + } + } + + if (result_digits > 0) + { + /* Append significant digits to the fraction part */ + lit_utf8_size_t to_copy = JERRY_MIN (num_of_digits, result_digits); + ecma_stringbuilder_append_raw (&builder, digits + copied_digits, to_copy); + result_digits -= to_copy; + + /* Append leading zeros */ + while (result_digits > 0) + { + ecma_stringbuilder_append_char (&builder, LIT_CHAR_0); + result_digits--; + } + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_number_prototype_object_to_number_convert */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_number_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + ecma_value_t this_value = ecma_builtin_number_prototype_object_value_of (this_arg); + + if (ECMA_IS_VALUE_ERROR (this_value)) + { + return this_value; + } + + if (builtin_routine_id == ECMA_NUMBER_PROTOTYPE_VALUE_OF) + { + return ecma_copy_value (this_value); + } + + ecma_number_t this_arg_number = ecma_get_number_from_value (this_value); + + switch (builtin_routine_id) + { + case ECMA_NUMBER_PROTOTYPE_TO_STRING: + { + return ecma_builtin_number_prototype_object_to_string (this_arg_number, arguments_list_p, arguments_number); + } + case ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING: + { + return ecma_builtin_number_prototype_object_to_string (this_arg_number, NULL, 0); + } + case ECMA_NUMBER_PROTOTYPE_TO_FIXED: + case ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL: + case ECMA_NUMBER_PROTOTYPE_TO_PRECISION: + { + const int option = NUMBER_ROUTINE_TO_FIXED + (builtin_routine_id - ECMA_NUMBER_PROTOTYPE_TO_FIXED); + return ecma_builtin_number_prototype_object_to_number_convert (this_arg_number, + arguments_list_p[0], + (number_routine_mode_t) option); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_number_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_NUMBER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.inc.h new file mode 100644 index 00000000..e5ac7dd1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Number.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_NUMBER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_NUMBER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_NUMBER_PROTOTYPE_TO_STRING, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_NUMBER_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_FIXED_UL, ECMA_NUMBER_PROTOTYPE_TO_FIXED, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TO_EXPONENTIAL_UL, ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TO_PRECISION_UL, ECMA_NUMBER_PROTOTYPE_TO_PRECISION, 1, 1) + +#endif /* JERRY_BUILTIN_NUMBER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.cpp new file mode 100644 index 00000000..89fa1ab9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.cpp @@ -0,0 +1,246 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-number-object.h" +#include "ecma-objects.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_NUMBER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_NUMBER_OBJECT_ROUTINE_START = 0, + ECMA_NUMBER_OBJECT_ROUTINE_IS_FINITE, + ECMA_NUMBER_OBJECT_ROUTINE_IS_NAN, + ECMA_NUMBER_OBJECT_ROUTINE_IS_INTEGER, + ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-number.inc.h" +#define BUILTIN_UNDERSCORED_ID number +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup number ECMA Number object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Number object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_number_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (arguments_list_len == 0) + { + ret_value = ecma_make_integer_value (0); + } + else + { + ecma_number_t num; + ret_value = ecma_op_to_numeric (arguments_list_p[0], &num, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (ret_value)) + { + ecma_value_t bigint = ret_value; + ret_value = ecma_bigint_to_number (bigint); + ecma_free_value (bigint); + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ret_value = ecma_make_number_value (num); + } + } + + return ret_value; +} /* ecma_builtin_number_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Number object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_number_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0) + { + return ecma_op_create_number_object (ecma_make_integer_value (0)); + } + +#if JERRY_BUILTIN_BIGINT + ecma_number_t num; + ecma_value_t value = ecma_op_to_numeric (arguments_list_p[0], &num, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + if (ecma_is_value_bigint (value)) + { + ecma_value_t bigint = value; + value = ecma_bigint_to_number (bigint); + ecma_free_value (bigint); + } + else + { + value = ecma_make_number_value (num); + } + + ecma_value_t result = ecma_op_create_number_object (value); + ecma_free_value (value); + return result; +#else /* !JERRY_BUILTIN_BIGINT */ + return ecma_op_create_number_object (arguments_list_p[0]); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* ecma_builtin_number_dispatch_construct */ + +/** + * The Number object 'isInteger' and 'isSafeInteger' routine + * + * See also: + * ECMA-262 v6, 20.1.2.3 + * ECMA-262 v6, 20.1.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_object_is_integer_helper (ecma_value_t arg, /**< routine's argument */ + ecma_number_t num, /**< this number */ + bool is_safe) /**< is the number safe */ +{ + if (ecma_number_is_nan (num) || ecma_number_is_infinity (num)) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t int_num; + + if (is_safe) + { + int_num = ecma_number_trunc (num); + + if (fabs (int_num) > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ECMA_VALUE_FALSE; + } + } + else + { + ecma_op_to_integer (arg, &int_num); + } + + return (int_num == num) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE; +} /* ecma_builtin_number_object_is_integer_helper */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_number_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + if (!ecma_is_value_number (arguments_list_p[0])) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]); + + switch (builtin_routine_id) + { + case ECMA_NUMBER_OBJECT_ROUTINE_IS_FINITE: + { + return ecma_make_boolean_value (!(ecma_number_is_nan (num) || ecma_number_is_infinity (num))); + } + case ECMA_NUMBER_OBJECT_ROUTINE_IS_NAN: + { + return ecma_make_boolean_value (ecma_number_is_nan (num)); + } + case ECMA_NUMBER_OBJECT_ROUTINE_IS_INTEGER: + case ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER: + { + bool is_safe = (builtin_routine_id == ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER); + return ecma_builtin_number_object_is_integer_helper (arguments_list_p[0], num, is_safe); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_number_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_NUMBER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h new file mode 100644 index 00000000..5a30cbf0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h @@ -0,0 +1,72 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Number built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_NUMBER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* ECMA-262 v5, 15.7.3.4 */ +NUMBER_VALUE (LIT_MAGIC_STRING_NAN, ECMA_BUILTIN_NUMBER_NAN, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MAX_VALUE_U, ECMA_BUILTIN_NUMBER_MAX, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.3 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MIN_VALUE_U, ECMA_BUILTIN_NUMBER_MIN, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.5 */ +NUMBER_VALUE (LIT_MAGIC_STRING_POSITIVE_INFINITY_U, ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v5, 15.7.3.6 */ +NUMBER_VALUE (LIT_MAGIC_STRING_NEGATIVE_INFINITY_U, ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.1.2.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_EPSILON_U, ECMA_BUILTIN_NUMBER_EPSILON, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.1.2.6 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MAX_SAFE_INTEGER_U, ECMA_BUILTIN_NUMBER_MAX_SAFE_INTEGER, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 20.1.2.8 */ +NUMBER_VALUE (LIT_MAGIC_STRING_MIN_SAFE_INTEGER_U, ECMA_BUILTIN_NUMBER_MIN_SAFE_INTEGER, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_NUMBER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_NUMBER_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_NUMBER */ + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ECMA_NUMBER_OBJECT_ROUTINE_IS_FINITE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_NAN, ECMA_NUMBER_OBJECT_ROUTINE_IS_NAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_INTEGER, ECMA_NUMBER_OBJECT_ROUTINE_IS_INTEGER, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_SAFE_INTEGER, ECMA_NUMBER_OBJECT_ROUTINE_IS_SAFE_INTEGER, 1, 1) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_FLOAT, LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_INT, LIT_MAGIC_STRING_PARSE_INT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.cpp new file mode 100644 index 00000000..28abfbb4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.cpp @@ -0,0 +1,513 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + /* Note: these 6 routines must be in this order */ + ECMA_OBJECT_PROTOTYPE_ROUTINE_START = 0, + ECMA_OBJECT_PROTOTYPE_TO_STRING, + ECMA_OBJECT_PROTOTYPE_VALUE_OF, + ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING, + ECMA_OBJECT_PROTOTYPE_GET_PROTO, + ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF, + ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY, + ECMA_OBJECT_PROTOTYPE_PROPERTY_IS_ENUMERABLE, + ECMA_OBJECT_PROTOTYPE_SET_PROTO, +#if JERRY_BUILTIN_ANNEXB + ECMA_OBJECT_PROTOTYPE_DEFINE_GETTER, + ECMA_OBJECT_PROTOTYPE_DEFINE_SETTER, + ECMA_OBJECT_PROTOTYPE_LOOKUP_GETTER, + ECMA_OBJECT_PROTOTYPE_LOOKUP_SETTER, +#endif /* JERRY_BUILTIN_ANNEXB */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-object-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID object_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup objectprototype ECMA Object.prototype object built-in + * @{ + */ + +/** + * The Object.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.2.4.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_builtin_helper_object_to_string (this_arg); +} /* ecma_builtin_object_prototype_object_to_string */ + +/** + * The Object.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v5, 15.2.4.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_op_to_object (this_arg); +} /* ecma_builtin_object_prototype_object_value_of */ + +/** + * The Object.prototype object's 'toLocaleString' routine + * + * See also: + * ECMA-262 v5, 15.2.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_op_invoke_by_magic_id (this_arg, LIT_MAGIC_STRING_TO_STRING_UL, &this_arg, 1); +} /* ecma_builtin_object_prototype_object_to_locale_string */ + +/** + * The Object.prototype object's 'hasOwnProperty' routine + * + * See also: + * ECMA-262 v5, 15.2.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_has_own_property (ecma_object_t *obj_p, /**< this argument */ + ecma_string_t *prop_name_p) /**< first argument */ +{ + return ecma_op_object_has_own_property (obj_p, prop_name_p); +} /* ecma_builtin_object_prototype_object_has_own_property */ + +/** + * The Object.prototype object's 'isPrototypeOf' routine + * + * See also: + * ECMA-262 v5, 15.2.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_is_prototype_of (ecma_object_t *obj_p, /**< this argument */ + ecma_value_t arg) /**< routine's first argument */ +{ + /* 3. Compare prototype to object */ + ecma_value_t v_obj_value = ecma_op_to_object (arg); + + if (ECMA_IS_VALUE_ERROR (v_obj_value)) + { + return v_obj_value; + } + + ecma_object_t *v_obj_p = ecma_get_object_from_value (v_obj_value); + + ecma_value_t ret_value = ecma_op_object_is_prototype_of (obj_p, v_obj_p); + + ecma_deref_object (v_obj_p); + + return ret_value; +} /* ecma_builtin_object_prototype_object_is_prototype_of */ + +/** + * The Object.prototype object's 'propertyIsEnumerable' routine + * + * See also: + * ECMA-262 v5, 15.2.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_prototype_object_property_is_enumerable (ecma_object_t *obj_p, /**< this argument */ + ecma_string_t *prop_name_p) /**< first argument */ +{ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc); + + if (!ecma_is_value_true (status)) + { + return status; + } + + bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE); + + ecma_free_property_descriptor (&prop_desc); + + return ecma_make_boolean_value (is_enumerable); +} /* ecma_builtin_object_prototype_object_property_is_enumerable */ + +#if JERRY_BUILTIN_ANNEXB +/** + * The Object.prototype object's '__defineGetter__' and '__defineSetter__' routine + * + * See also: + * ECMA-262 v11, B.2.2.2 + * ECMA-262 v11, B.2.2.3 + * + * @return ECMA_VALUE_ERROR - if the operation fails, + * ECMA_VALUE_UNDEFINED - otherwise + */ +static ecma_value_t +ecma_builtin_object_prototype_define_getter_setter (ecma_value_t this_arg, /**< this argument */ + ecma_value_t prop, /**< property */ + ecma_value_t accessor, /**< getter/setter function */ + bool define_getter) /**< true - defineGetter method + false - defineSetter method */ +{ + /* 1. */ + ecma_value_t to_obj = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_obj)) + { + return to_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_obj); + + /* 2. */ + if (!ecma_op_is_callable (accessor)) + { + ecma_deref_object (obj_p); + return ecma_raise_type_error (ECMA_ERR_GETTER_IS_NOT_CALLABLE); + } + + ecma_object_t *accessor_obj_p = ecma_get_object_from_value (accessor); + + /* 3. */ + ecma_property_descriptor_t desc = ecma_make_empty_property_descriptor (); + desc.flags |= (JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED + | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_SHOULD_THROW); + + if (define_getter) + { + desc.get_p = accessor_obj_p; + desc.flags |= JERRY_PROP_IS_GET_DEFINED; + } + else + { + desc.set_p = accessor_obj_p; + desc.flags |= JERRY_PROP_IS_SET_DEFINED; + } + + /* 4. */ + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + ecma_deref_object (obj_p); + return ECMA_VALUE_ERROR; + } + + /* 5. */ + ecma_value_t define_prop = ecma_op_object_define_own_property (obj_p, prop_name_p, &desc); + + ecma_deref_object (obj_p); + ecma_deref_ecma_string (prop_name_p); + + if (ECMA_IS_VALUE_ERROR (define_prop)) + { + return define_prop; + } + + /* 6. */ + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_object_prototype_define_getter_setter */ + +/** + * The Object.prototype object's '__lookupGetter__' and '__lookupSetter__' routine + * + * See also: + * ECMA-262 v11, B.2.2.4 + * ECMA-262 v11, B.2.2.5 + * + * @return ECMA_VALUE_ERROR - if the operation fails, + * ECMA_VALUE_UNDEFINED - if the property was not found + * Accessor property - otherwise + */ +static ecma_value_t +ecma_builtin_object_prototype_lookup_getter_setter (ecma_value_t this_arg, /**< this argument */ + ecma_value_t prop, /**< property */ + bool lookup_getter) /**< true - lookupGetter method + false - lookupSetter method */ +{ + /* 1. */ + ecma_value_t to_obj = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_obj)) + { + return to_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_obj); + + /* 2. */ + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + ecma_deref_object (obj_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; + + ecma_ref_object (obj_p); + + /* 3. */ + while (true) + { + /* 3.a */ + ecma_property_descriptor_t desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + ret_value = get_desc; + ecma_deref_object (obj_p); + break; + } + + /* 3.b */ + if (ecma_is_value_true (get_desc)) + { + if ((desc.flags & JERRY_PROP_IS_SET_DEFINED) || (desc.flags & JERRY_PROP_IS_GET_DEFINED)) + { + if (lookup_getter && desc.get_p != NULL) + { + ecma_ref_object (desc.get_p); + ret_value = ecma_make_object_value (desc.get_p); + } + else if (!lookup_getter && desc.set_p != NULL) + { + ecma_ref_object (desc.set_p); + ret_value = ecma_make_object_value (desc.set_p); + } + } + + ecma_free_property_descriptor (&desc); + ecma_deref_object (obj_p); + break; + } + + /* 3.c */ + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_p); + ecma_deref_object (obj_p); + + if (proto_p == NULL) + { + break; + } + else if (JERRY_UNLIKELY (proto_p == ECMA_OBJECT_POINTER_ERROR)) + { + ret_value = ECMA_VALUE_ERROR; + break; + } + + /* Advance up on prototype chain. */ + obj_p = proto_p; + } + + ecma_free_value (to_obj); + ecma_deref_ecma_string (prop_name_p); + + return ret_value; +} /* ecma_builtin_object_prototype_lookup_getter_setter */ +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + /* no specialization */ + if (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_VALUE_OF) + { + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_TO_STRING) + { + return ecma_builtin_object_prototype_object_to_string (this_arg); + } + + JERRY_ASSERT (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_VALUE_OF); + + return ecma_builtin_object_prototype_object_value_of (this_arg); + } + + if (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF) + { + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF) + { + /* 15.2.4.6.1. */ + if (!ecma_is_value_object (arguments_list_p[0])) + { + return ECMA_VALUE_FALSE; + } + } + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING) + { + return ecma_builtin_object_prototype_object_to_locale_string (this_arg); + } + + ecma_value_t to_object = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_object)) + { + return to_object; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_object); + + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_GET_PROTO) + { + ret_value = ecma_builtin_object_object_get_prototype_of (obj_p); + } + else + { + ret_value = ecma_builtin_object_prototype_object_is_prototype_of (obj_p, arguments_list_p[0]); + } + + ecma_deref_object (obj_p); + + return ret_value; + } + + JERRY_ASSERT (builtin_routine_id >= ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY); + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_SET_PROTO) + { + return ecma_builtin_object_object_set_proto (this_arg, arguments_list_p[0]); + } +#if JERRY_BUILTIN_ANNEXB + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_LOOKUP_GETTER) + { + return ecma_builtin_object_prototype_lookup_getter_setter (this_arg, arguments_list_p[0], true); + } + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_LOOKUP_SETTER) + { + return ecma_builtin_object_prototype_lookup_getter_setter (this_arg, arguments_list_p[0], false); + } + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_DEFINE_GETTER) + { + return ecma_builtin_object_prototype_define_getter_setter (this_arg, + arguments_list_p[0], + arguments_list_p[1], + true); + } + else if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_DEFINE_SETTER) + { + return ecma_builtin_object_prototype_define_getter_setter (this_arg, + arguments_list_p[0], + arguments_list_p[1], + false); + } +#endif /* JERRY_BUILTIN_ANNEXB */ + + ecma_string_t *prop_name_p = ecma_op_to_property_key (arguments_list_p[0]); + + if (prop_name_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t to_object = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_object)) + { + ecma_deref_ecma_string (prop_name_p); + return to_object; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (to_object); + + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY) + { + ret_value = ecma_builtin_object_prototype_object_has_own_property (obj_p, prop_name_p); + } + else + { + ret_value = ecma_builtin_object_prototype_object_property_is_enumerable (obj_p, prop_name_p); + } + + ecma_deref_ecma_string (prop_name_p); + ecma_deref_object (obj_p); + + return ret_value; +} /* ecma_builtin_object_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h new file mode 100644 index 00000000..b218eda5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h @@ -0,0 +1,49 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Object.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.2.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_OBJECT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ACCESSOR_READ_WRITE (LIT_MAGIC_STRING__PROTO__, + ECMA_OBJECT_PROTOTYPE_GET_PROTO, + ECMA_OBJECT_PROTOTYPE_SET_PROTO, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_OBJECT_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_OBJECT_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL, ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL, ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, ECMA_OBJECT_PROTOTYPE_PROPERTY_IS_ENUMERABLE, 1, 1) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_DEFINE_GETTER, ECMA_OBJECT_PROTOTYPE_DEFINE_GETTER, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DEFINE_SETTER, ECMA_OBJECT_PROTOTYPE_DEFINE_SETTER, 2, 2) +ROUTINE (LIT_MAGIC_STRING_LOOKUP_GETTER, ECMA_OBJECT_PROTOTYPE_LOOKUP_GETTER, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOOKUP_SETTER, ECMA_OBJECT_PROTOTYPE_LOOKUP_SETTER, 1, 1) +#endif /* JERRY_BUILTIN_ANNEXB*/ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp new file mode 100644 index 00000000..ecadb696 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp @@ -0,0 +1,1555 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_OBJECT_ROUTINE_START = 0, + + ECMA_OBJECT_ROUTINE_CREATE, + ECMA_OBJECT_ROUTINE_IS, + ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY, + ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_ASSIGN, + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR, + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS, + ECMA_OBJECT_ROUTINE_HAS_OWN, + ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF, + ECMA_OBJECT_ROUTINE_FROM_ENTRIES, + ECMA_OBJECT_ROUTINE_KEYS, + ECMA_OBJECT_ROUTINE_VALUES, + ECMA_OBJECT_ROUTINE_ENTRIES, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES, + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_FREEZE, + ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS, + ECMA_OBJECT_ROUTINE_SEAL, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE, + ECMA_OBJECT_ROUTINE_IS_FROZEN, + ECMA_OBJECT_ROUTINE_IS_SEALED, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-object.inc.h" +#define BUILTIN_UNDERSCORED_ID object +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup object ECMA Object object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Object object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_object_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (arguments_list_len == 0 || ecma_is_value_undefined (arguments_list_p[0]) + || ecma_is_value_null (arguments_list_p[0])) + { + return ecma_make_object_value (ecma_op_create_object_object_noarg ()); + } + + return ecma_op_to_object (arguments_list_p[0]); +} /* ecma_builtin_object_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Object object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_object_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (JERRY_CONTEXT (current_new_target_p) != ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT)) + { + ecma_object_t *prototype_obj_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *object_p = ecma_create_object (prototype_obj_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (prototype_obj_p); + + return ecma_make_object_value (object_p); + } + + return ecma_builtin_object_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_object_dispatch_construct */ + +/** + * The Object object's 'getPrototypeOf' routine + * + * See also: + * ECMA-262 v5, 15.2.3.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p) /**< routine's argument */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_get_prototype_of (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (obj_p); + + if (proto_cp != JMEM_CP_NULL) + { + ecma_object_t *prototype_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (prototype_p); + return ecma_make_object_value (prototype_p); + } + + return ECMA_VALUE_NULL; +} /* ecma_builtin_object_object_get_prototype_of */ + +/** + * The Object object's 'setPrototypeOf' routine + * + * See also: + * ES2015 19.1.2.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_set_prototype_of (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 1., 2. */ + if (!ecma_op_require_object_coercible (arg1)) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + if (!ecma_is_value_object (arg2) && !ecma_is_value_null (arg2)) + { + return ecma_raise_type_error (ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL); + } + + /* 4. */ + if (!ecma_is_value_object (arg1)) + { + return ecma_copy_value (arg1); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arg1); + ecma_value_t status; + + /* 5. */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + status = ecma_proxy_object_set_prototype_of (obj_p, arg2); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2); +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_SET_PROTOTYPE); + } + + JERRY_ASSERT (ecma_is_value_true (status)); + ecma_ref_object (obj_p); + + return arg1; +} /* ecma_builtin_object_object_set_prototype_of */ + +/** + * The Object object's set __proto__ routine + * + * See also: + * ECMA-262 v6, B.2.2.1.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_set_proto (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 1., 2. */ + if (!ecma_op_require_object_coercible (arg1)) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + if (!ecma_is_value_object (arg2) && !ecma_is_value_null (arg2)) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 4. */ + if (!ecma_is_value_object (arg1)) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arg1); + ecma_value_t status; + + /* 5. */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + status = ecma_proxy_object_set_prototype_of (obj_p, arg2); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2); +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_SET_PROTOTYPE); + } + + JERRY_ASSERT (ecma_is_value_true (status)); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_object_object_set_proto */ + +/** + * SetIntegrityLevel operation + * + * See also: + * ECMA-262 v6, 7.3.14 + * + * @return ECMA_VALUE_ERROR - if the operation raised an error + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the integrity level has been set successfully + */ +static ecma_value_t +ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */ + bool is_seal) /**< true - set "sealed" + * false - set "frozen" */ +{ + /* 3. */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p); + + if (!ecma_is_value_true (status)) + { + return status; + } + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + ecma_op_ordinary_object_prevent_extensions (obj_p); + } + + /* 6. */ + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (props_p == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = props_p->buffer_p; + + if (is_seal) + { + /* 8.a */ + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (props_p); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + continue; + } + + prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_CONFIGURABLE; + prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + + /* 8.a.i */ + ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, property_name_p, &prop_desc); + + ecma_free_property_descriptor (&prop_desc); + + /* 8.a.ii */ + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + ecma_collection_free (props_p); + return define_own_prop_ret; + } + + ecma_free_value (define_own_prop_ret); + } + } + else + { + /* 9.a */ + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + /* 9.1 */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (props_p); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + continue; + } + + /* 9.2 */ + if ((prop_desc.flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + == (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + { + prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_WRITABLE; + } + + prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_CONFIGURABLE; + prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + + /* 9.3 */ + ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, property_name_p, &prop_desc); + + ecma_free_property_descriptor (&prop_desc); + + /* 9.4 */ + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + ecma_collection_free (props_p); + return define_own_prop_ret; + } + + ecma_free_value (define_own_prop_ret); + } + } + + ecma_collection_free (props_p); + + return ECMA_VALUE_TRUE; +} /* ecma_builtin_object_set_integrity_level */ + +/** + * The Object object's 'seal' routine + * + * See also: + * ECMA-262 v5, 15.2.3.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_seal (ecma_object_t *obj_p) /**< routine's argument */ +{ + ecma_value_t status = ecma_builtin_object_set_integrity_level (obj_p, true); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_OBJECT_CANNOT_BE_SEALED); + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 4. */ + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_seal */ + +/** + * The Object object's 'freeze' routine + * + * See also: + * ECMA-262 v5, 15.2.3.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_freeze (ecma_object_t *obj_p) /**< routine's argument */ +{ + ecma_value_t status = ecma_builtin_object_set_integrity_level (obj_p, false); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + +#if JERRY_BUILTIN_PROXY + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_OBJECT_CANNOT_BE_FROZEN); + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 4. */ + ecma_ref_object (obj_p); + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_freeze */ + +/** + * The Object object's 'preventExtensions' routine + * + * See also: + * ECMA-262 v5, 15.2.3.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_prevent_extensions (ecma_object_t *obj_p) /**< routine's argument */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + if (ecma_is_value_false (status)) + { + return ecma_raise_type_error (ECMA_ERR_SET_EXTENSIBLE_PROPERTY); + } + + JERRY_ASSERT (ecma_is_value_true (status)); + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + ecma_op_ordinary_object_prevent_extensions (obj_p); +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + ecma_ref_object (obj_p); + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_prevent_extensions */ + +/** + * The Object object's 'isSealed' and 'isFrozen' routines + * + * See also: + * ECMA-262 v5, 15.2.3.11 + * ECMA-262 v5, 15.2.3.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's argument */ + int mode) /**< routine mode */ +{ + JERRY_ASSERT (mode == ECMA_OBJECT_ROUTINE_IS_FROZEN || mode == ECMA_OBJECT_ROUTINE_IS_SEALED); + + /* 3. */ + bool is_extensible; +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t status = ecma_proxy_object_is_extensible (obj_p); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + is_extensible = ecma_is_value_true (status); + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + is_extensible = ecma_op_ordinary_object_is_extensible (obj_p); + } + + if (is_extensible) + { + return ECMA_VALUE_FALSE; + } + + /* the value can be updated in the loop below */ + ecma_value_t ret_value = ECMA_VALUE_TRUE; + + /* 2. */ + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (props_p == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = props_p->buffer_p; + + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + /* 2.a */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ret_value = status; + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (status)) + { + continue; + } + + bool is_writable_data = ((prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE)) + == (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE)); + bool is_configurable = (prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE); + + ecma_free_property_descriptor (&prop_desc); + + /* 2.b for isFrozen */ + /* 2.b for isSealed, 2.c for isFrozen */ + if ((mode == ECMA_OBJECT_ROUTINE_IS_FROZEN && is_writable_data) || is_configurable) + { + ret_value = ECMA_VALUE_FALSE; + break; + } + } + + ecma_collection_free (props_p); + + return ret_value; +} /* ecma_builtin_object_test_integrity_level */ + +/** + * The Object object's 'isExtensible' routine + * + * See also: + * ECMA-262 v5, 15.2.3.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_is_extensible (ecma_object_t *obj_p) /**< routine's argument */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_is_extensible (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_make_boolean_value (ecma_op_ordinary_object_is_extensible (obj_p)); +} /* ecma_builtin_object_object_is_extensible */ + +/** + * Common implementation of the Object object's 'keys', 'values', 'entries' routines + * + * See also: + * ECMA-262 v11, 19.1.2.17 + * ECMA-262 v11, 19.1.2.22 + * ECMA-262 v11, 19.1.2.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_keys_values_helper (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_enumerable_property_names_options_t option) /**< listing option */ +{ + /* 2. */ + ecma_collection_t *props_p = ecma_op_object_get_enumerable_property_names (obj_p, option); + + if (props_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + return ecma_op_new_array_object_from_collection (props_p, option != ECMA_ENUMERABLE_PROPERTY_KEYS); +} /* ecma_builtin_object_object_keys_values_helper */ + +/** + * The Object object's 'getOwnPropertyDescriptor' routine + * + * See also: + * ECMA-262 v5, 15.2.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_string_t *name_str_p) /**< routine's second argument */ +{ + /* 3. */ + ecma_property_descriptor_t prop_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, name_str_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (status)) + { + /* 4. */ + ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + + ecma_free_property_descriptor (&prop_desc); + + return ecma_make_object_value (desc_obj_p); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_object_object_get_own_property_descriptor */ + +/** + * The Object object's 'getOwnPropertyDescriptors' routine + * + * See also: + * ECMA-262 v11, 19.1.2.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) /**< routine's first argument */ +{ + /* 2 */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (prop_names_p == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *names_buffer_p = prop_names_p->buffer_p; + + /* 3 */ + ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + ecma_object_t *descriptors_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 4 */ + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (names_buffer_p[i]); + + /* 4.a */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_deref_object (descriptors_p); + ecma_collection_free (prop_names_p); + + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (status)) + { + /* 4.b */ + ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + /* 4.c */ + ecma_property_value_t *value_p = ecma_create_named_data_property (descriptors_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + value_p->value = ecma_make_object_value (desc_obj_p); + + ecma_deref_object (desc_obj_p); + ecma_free_property_descriptor (&prop_desc); + } + } + + ecma_collection_free (prop_names_p); + + return ecma_make_object_value (descriptors_p); +} /* ecma_builtin_object_object_get_own_property_descriptors */ + +/** + * The Object object's 'defineProperties' routine + * + * See also: + * ECMA-262 v5, 15.2.3.7 + * ECMA-262 v11, 19.1.2.3.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 2. */ + ecma_value_t props = ecma_op_to_object (arg2); + + if (ECMA_IS_VALUE_ERROR (props)) + { + return props; + } + + ecma_object_t *props_p = ecma_get_object_from_value (props); + + /* 3. */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (props_p, JERRY_PROPERTY_FILTER_ALL); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + +#if JERRY_BUILTIN_PROXY + if (prop_names_p == NULL) + { + ecma_deref_object (props_p); + return ret_value; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = prop_names_p->buffer_p; + + /* 4. */ + JMEM_DEFINE_LOCAL_ARRAY (property_descriptors, prop_names_p->item_count, ecma_property_descriptor_t); + uint32_t property_descriptor_number = 0; + ecma_collection_t *enum_prop_names = ecma_new_collection (); + + /* 5. */ + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[i]); + + ecma_property_descriptor_t prop_desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (props_p, prop_name_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + goto cleanup; + } + + if (ecma_is_value_true (get_desc)) + { + if (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) + { + ecma_value_t desc_obj = ecma_op_object_get (props_p, prop_name_p); + + if (ECMA_IS_VALUE_ERROR (desc_obj)) + { + ecma_free_property_descriptor (&prop_desc); + goto cleanup; + } + + ecma_value_t conv_result = + ecma_op_to_property_descriptor (desc_obj, &property_descriptors[property_descriptor_number]); + + property_descriptors[property_descriptor_number].flags |= JERRY_PROP_SHOULD_THROW; + + ecma_free_value (desc_obj); + + if (ECMA_IS_VALUE_ERROR (conv_result)) + { + ecma_free_property_descriptor (&prop_desc); + goto cleanup; + } + + property_descriptor_number++; + ecma_free_value (conv_result); + ecma_ref_ecma_string (prop_name_p); + ecma_collection_push_back (enum_prop_names, buffer_p[i]); + } + + ecma_free_property_descriptor (&prop_desc); + } + } + + /* 6. */ + for (uint32_t i = 0; i < enum_prop_names->item_count; i++) + { + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (enum_prop_names->buffer_p[i]); + + ecma_value_t define_own_prop_ret = + ecma_op_object_define_own_property (obj_p, prop_name_p, &property_descriptors[i]); + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + goto cleanup; + } + + ecma_free_value (define_own_prop_ret); + } + + ecma_ref_object (obj_p); + ret_value = ecma_make_object_value (obj_p); + +cleanup: + /* Clean up. */ + for (uint32_t index = 0; index < property_descriptor_number; index++) + { + ecma_free_property_descriptor (&property_descriptors[index]); + } + + ecma_collection_free (enum_prop_names); + + JMEM_FINALIZE_LOCAL_ARRAY (property_descriptors); + + ecma_collection_free (prop_names_p); + + ecma_deref_object (props_p); + + return ret_value; +} /* ecma_builtin_object_object_define_properties */ + +/** + * The Object object's 'create' routine + * + * See also: + * ECMA-262 v5, 15.2.3.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_create (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 1. */ + if (!ecma_is_value_object (arg1) && !ecma_is_value_null (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = NULL; + + if (!ecma_is_value_null (arg1)) + { + obj_p = ecma_get_object_from_value (arg1); + } + /* 2-3. */ + ecma_object_t *result_obj_p = ecma_op_create_object_object_noarg_and_set_prototype (obj_p); + + /* 4. */ + if (!ecma_is_value_undefined (arg2)) + { + ecma_value_t obj = ecma_builtin_object_object_define_properties (result_obj_p, arg2); + + if (ECMA_IS_VALUE_ERROR (obj)) + { + ecma_deref_object (result_obj_p); + return obj; + } + + ecma_free_value (obj); + } + + /* 5. */ + return ecma_make_object_value (result_obj_p); +} /* ecma_builtin_object_object_create */ + +/** + * The Object object's 'defineProperty' routine + * + * See also: + * ECMA-262 v5, 15.2.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_object_define_property (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_string_t *name_str_p, /**< routine's second argument */ + ecma_value_t arg3) /**< routine's third argument */ +{ + ecma_property_descriptor_t prop_desc; + + ecma_value_t conv_result = ecma_op_to_property_descriptor (arg3, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (conv_result)) + { + return conv_result; + } + + prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + + ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc); + + ecma_free_property_descriptor (&prop_desc); + ecma_free_value (conv_result); + + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) + { + return define_own_prop_ret; + } + + if (ecma_is_value_false (define_own_prop_ret)) + { + return ecma_raise_type_error (ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED); + } + + JERRY_ASSERT (ecma_is_value_true (define_own_prop_ret)); + + ecma_ref_object (obj_p); + ecma_free_value (define_own_prop_ret); + + return ecma_make_object_value (obj_p); +} /* ecma_builtin_object_object_define_property */ + +/** + * The Object object's 'assign' routine + * + * See also: + * ECMA-262 v6, 19.1.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object */ + const ecma_value_t arguments_list_p[], /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 4-5. */ + for (uint32_t i = 0; i < arguments_list_len && ecma_is_value_empty (ret_value); i++) + { + ecma_value_t next_source = arguments_list_p[i]; + + /* 5.a */ + if (ecma_is_value_undefined (next_source) || ecma_is_value_null (next_source)) + { + continue; + } + + /* 5.b.i */ + ecma_value_t from_value = ecma_op_to_object (next_source); + /* null and undefied cases are handled above, so this must be a valid object */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (from_value)); + + ecma_object_t *from_obj_p = ecma_get_object_from_value (from_value); + + /* 5.b.iii */ + ecma_collection_t *props_p = ecma_op_object_own_property_keys (from_obj_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (props_p == NULL) + { + ecma_deref_object (from_obj_p); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *buffer_p = props_p->buffer_p; + + for (uint32_t j = 0; (j < props_p->item_count) && ecma_is_value_empty (ret_value); j++) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[j]); + + /* 5.c.i-ii */ + ecma_property_descriptor_t prop_desc; + ecma_value_t desc_status = ecma_op_object_get_own_property_descriptor (from_obj_p, property_name_p, &prop_desc); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (desc_status)) + { + ret_value = desc_status; + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (desc_status)) + { + continue; + } + + /* 5.c.iii */ + if (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) + { + /* 5.c.iii.1 */ + ecma_value_t prop_value = ecma_op_object_get (from_obj_p, property_name_p); + + /* 5.c.iii.2 */ + if (ECMA_IS_VALUE_ERROR (prop_value)) + { + ret_value = prop_value; + } + else + { + /* 5.c.iii.3 */ + ecma_value_t status = ecma_op_object_put (target_p, property_name_p, prop_value, true); + + /* 5.c.iii.4 */ + if (ECMA_IS_VALUE_ERROR (status)) + { + ret_value = status; + } + } + + ecma_free_value (prop_value); + } + + ecma_free_property_descriptor (&prop_desc); + } + + ecma_deref_object (from_obj_p); + ecma_collection_free (props_p); + } + + /* 6. */ + if (ecma_is_value_empty (ret_value)) + { + ecma_ref_object (target_p); + return ecma_make_object_value (target_p); + } + + return ret_value; +} /* ecma_builtin_object_object_assign */ + +/** + * The Object object's 'is' routine + * + * See also: + * ECMA-262 v6, 19.1.2.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_is (ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + return ecma_op_same_value (arg1, arg2) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE; +} /* ecma_builtin_object_object_is */ + +/** + * The Object object's 'fromEntries' routine + * + * See also: + * ECMA-262 v10, 19.1.2.7 + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_from_entries (ecma_value_t iterator) /**< object's iterator */ +{ + JERRY_ASSERT (ecma_op_require_object_coercible (iterator)); + /* 2 */ + ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + ecma_object_t *obj_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 6.a */ + ecma_value_t next_method; + ecma_value_t result = ecma_op_get_iterator (iterator, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (obj_p); + return result; + } + + const ecma_value_t original_iterator = result; + + /* 6.b */ + while (true) + { + /* 6.a.i */ + result = ecma_op_iterator_step (original_iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + /* 6.a.ii */ + if (ecma_is_value_false (result)) + { + break; + } + + /* 6.a.iii */ + const ecma_value_t next = result; + result = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + /* 6.a.iv */ + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + ecma_raise_type_error (ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT); + result = ecma_op_iterator_close (original_iterator); + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + goto cleanup_iterator; + } + + /* 6.a.v-vi */ + ecma_object_t *next_object_p = ecma_get_object_from_value (result); + + result = ecma_op_object_get_by_index (next_object_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_op_iterator_close (original_iterator); + goto cleanup_iterator; + } + + const ecma_value_t key = result; + + result = ecma_op_object_get_by_index (next_object_p, 1); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_free_value (key); + ecma_op_iterator_close (original_iterator); + goto cleanup_iterator; + } + + /* 6.a.vii */ + const ecma_value_t value = result; + ecma_string_t *property_key = ecma_op_to_property_key (key); + + if (property_key == NULL) + { + ecma_deref_object (next_object_p); + ecma_free_value (key); + ecma_op_iterator_close (original_iterator); + result = ECMA_VALUE_ERROR; + goto cleanup_iterator; + } + + ecma_property_t *property_p = ecma_find_named_property (obj_p, property_key); + + if (property_p == NULL) + { + ecma_property_value_t *prop; + prop = + ecma_create_named_data_property (obj_p, property_key, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + prop->value = ecma_copy_value_if_not_object (value); + } + else + { + ecma_named_data_property_assign_value (obj_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + } + + ecma_deref_ecma_string (property_key); + ecma_free_value (key); + ecma_free_value (value); + ecma_deref_object (next_object_p); + } + + ecma_ref_object (obj_p); + result = ecma_make_object_value (obj_p); + +cleanup_iterator: + ecma_free_value (original_iterator); + ecma_free_value (next_method); + ecma_deref_object (obj_p); + + return result; +} /* ecma_builtin_object_from_entries */ + +/** + * GetOwnPropertyKeys abstract method + * + * See also: + * ECMA-262 v11, 19.1.2.11.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_object_get_own_property_keys (ecma_value_t this_arg, /**< this argument */ + uint16_t type) /**< routine type */ +{ + /* 1. */ + ecma_value_t object = ecma_op_to_object (this_arg); + + if (ECMA_IS_VALUE_ERROR (object)) + { + return object; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (object); + + /* 2. */ + jerry_property_filter_t filter = JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS; + + if (type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) + { + filter = (jerry_property_filter_t) ((unsigned int) JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS | (unsigned int) JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES); + } + + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, filter); + + if (props_p == NULL) + { + ecma_deref_object (obj_p); + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_collection_t *name_list_p = ecma_new_collection (); + + /* 4. */ + for (uint32_t i = 0; i < props_p->item_count; i++) + { + ecma_value_t prop_name = props_p->buffer_p[i]; + ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name); + + if ((ecma_prop_name_is_symbol (name_p) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) + || (ecma_is_value_string (prop_name) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES)) + { + ecma_ref_ecma_string (name_p); + ecma_collection_push_back (name_list_p, prop_name); + } + } + + ecma_value_t result_array = ecma_op_new_array_object_from_collection (name_list_p, false); + + ecma_deref_object (obj_p); + ecma_collection_free (props_p); + + return result_array; +} /* ecma_op_object_get_own_property_keys */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_object_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + ecma_value_t arg1 = arguments_list_p[0]; + ecma_value_t arg2 = arguments_list_p[1]; + + /* No specialization for the arguments */ + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_CREATE: + { + return ecma_builtin_object_object_create (arg1, arg2); + } + case ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF: + { + return ecma_builtin_object_object_set_prototype_of (arg1, arg2); + } + case ECMA_OBJECT_ROUTINE_IS: + { + return ecma_builtin_object_object_is (arg1, arg2); + } + default: + { + break; + } + } + + ecma_object_t *obj_p; + + if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES) + { + if (!ecma_is_value_object (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + obj_p = ecma_get_object_from_value (arg1); + + if (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY) + { + ecma_string_t *prop_name_p = ecma_op_to_property_key (arg2); + + if (prop_name_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_object_object_define_property (obj_p, prop_name_p, arguments_list_p[2]); + + ecma_deref_ecma_string (prop_name_p); + return result; + } + + JERRY_ASSERT (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES); + return ecma_builtin_object_object_define_properties (obj_p, arg2); + } + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_ENTRIES) + { + ecma_value_t object = ecma_op_to_object (arg1); + if (ECMA_IS_VALUE_ERROR (object)) + { + return object; + } + + obj_p = ecma_get_object_from_value (object); + + ecma_value_t result; + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF: + { + result = ecma_builtin_object_object_get_prototype_of (obj_p); + break; + } + case ECMA_OBJECT_ROUTINE_ASSIGN: + { + result = ecma_builtin_object_object_assign (obj_p, arguments_list_p + 1, arguments_number - 1); + break; + } + case ECMA_OBJECT_ROUTINE_ENTRIES: + case ECMA_OBJECT_ROUTINE_VALUES: + case ECMA_OBJECT_ROUTINE_KEYS: + { + JERRY_ASSERT (builtin_routine_id - ECMA_OBJECT_ROUTINE_KEYS < ECMA_ENUMERABLE_PROPERTY__COUNT); + + const int option = builtin_routine_id - ECMA_OBJECT_ROUTINE_KEYS; + result = + ecma_builtin_object_object_keys_values_helper (obj_p, (ecma_enumerable_property_names_options_t) option); + break; + } + case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR: + { + ecma_string_t *prop_name_p = ecma_op_to_property_key (arg2); + + if (prop_name_p == NULL) + { + result = ECMA_VALUE_ERROR; + break; + } + + result = ecma_builtin_object_object_get_own_property_descriptor (obj_p, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + break; + } + case ECMA_OBJECT_ROUTINE_HAS_OWN: + { + ecma_string_t *prop_name_p = ecma_op_to_property_key (arg2); + + if (prop_name_p == NULL) + { + result = ECMA_VALUE_ERROR; + break; + } + + result = ecma_op_object_has_own_property (obj_p, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + break; + } + case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS: + { + result = ecma_builtin_object_object_get_own_property_descriptors (obj_p); + break; + } + case ECMA_OBJECT_ROUTINE_FROM_ENTRIES: + { + result = ecma_builtin_object_from_entries (arg1); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_deref_object (obj_p); + return result; + } + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) + { + return ecma_op_object_get_own_property_keys (arg1, builtin_routine_id); + } + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_SEAL) + { + if (!ecma_is_value_object (arg1)) + { + return ecma_copy_value (arg1); + } + + obj_p = ecma_get_object_from_value (arg1); + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_SEAL: + { + return ecma_builtin_object_object_seal (obj_p); + } + case ECMA_OBJECT_ROUTINE_FREEZE: + { + return ecma_builtin_object_object_freeze (obj_p); + } + case ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS: + { + return ecma_builtin_object_object_prevent_extensions (obj_p); + } + default: + { + JERRY_UNREACHABLE (); + } + } + } + else + { + JERRY_ASSERT (builtin_routine_id <= ECMA_OBJECT_ROUTINE_IS_SEALED); + + if (!ecma_is_value_object (arg1)) + { + return ecma_make_boolean_value (builtin_routine_id != ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE); + } + + obj_p = ecma_get_object_from_value (arg1); + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_IS_SEALED: + case ECMA_OBJECT_ROUTINE_IS_FROZEN: + { + return ecma_builtin_object_test_integrity_level (obj_p, builtin_routine_id); + } + case ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE: + { + return ecma_builtin_object_object_is_extensible (obj_p); + } + default: + { + JERRY_UNREACHABLE (); + } + } + } +} /* ecma_builtin_object_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.h new file mode 100644 index 00000000..f31b2617 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ECMA_BUILTIN_OBJECT_H +#define ECMA_BUILTIN_OBJECT_H + +#include "ecma-globals.h" + +ecma_value_t ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_value_t ecma_builtin_object_object_set_prototype_of (ecma_value_t arg1, ecma_value_t arg2); + +ecma_value_t ecma_builtin_object_object_set_proto (ecma_value_t arg1, ecma_value_t arg2); + +ecma_value_t ecma_builtin_object_object_prevent_extensions (ecma_object_t *obj_p); + +ecma_value_t ecma_builtin_object_object_is_extensible (ecma_object_t *obj_p); + +ecma_value_t ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, ecma_string_t *name_str_p); +ecma_value_t +ecma_builtin_object_object_define_property (ecma_object_t *obj_p, ecma_string_t *name_str_p, ecma_value_t arg3); + +#endif /* !ECMA_BUILTIN_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h new file mode 100644 index 00000000..ee02ad62 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h @@ -0,0 +1,59 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Object built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.2.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_OBJECT_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SEAL, ECMA_OBJECT_ROUTINE_SEAL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FREEZE, ECMA_OBJECT_ROUTINE_FREEZE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL, ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_SEALED_UL, ECMA_OBJECT_ROUTINE_IS_SEALED, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_FROZEN_UL, ECMA_OBJECT_ROUTINE_IS_FROZEN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_EXTENSIBLE, ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_OBJECT_ROUTINE_ENTRIES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_VALUES, ECMA_OBJECT_ROUTINE_VALUES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_OBJECT_ROUTINE_KEYS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR, 2, 2) +ROUTINE (LIT_MAGIC_STRING_HAS_OWN_UL, ECMA_OBJECT_ROUTINE_HAS_OWN, 2, 2) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_OBJECT_FROM_ENTRIES, ECMA_OBJECT_ROUTINE_FROM_ENTRIES, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CREATE, ECMA_OBJECT_ROUTINE_CREATE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL, ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF, 2, 2) +ROUTINE (LIT_MAGIC_STRING_ASSIGN, ECMA_OBJECT_ROUTINE_ASSIGN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_IS, ECMA_OBJECT_ROUTINE_IS, 2, 2) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.cpp new file mode 100644 index 00000000..b24f6d5b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.cpp @@ -0,0 +1,93 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-globals.h" +#include "ecma-promise-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_PROMISE_PROTOTYPE_ROUTINE_START = 0, + ECMA_PROMISE_PROTOTYPE_ROUTINE_THEN, + ECMA_PROMISE_PROTOTYPE_ROUTINE_CATCH, + ECMA_PROMISE_PROTOTYPE_ROUTINE_FINALLY +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-promise-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID promise_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup promiseprototype ECMA Promise.prototype object built-in + * @{ + */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_promise_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { + case ECMA_PROMISE_PROTOTYPE_ROUTINE_THEN: + { + return ecma_promise_then (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_PROMISE_PROTOTYPE_ROUTINE_CATCH: + { + ecma_value_t args[] = { ECMA_VALUE_UNDEFINED, arguments_list_p[0] }; + return ecma_op_invoke_by_magic_id (this_arg, LIT_MAGIC_STRING_THEN, args, 2); + } + case ECMA_PROMISE_PROTOTYPE_ROUTINE_FINALLY: + { + return ecma_promise_finally (this_arg, arguments_list_p[0]); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_promise_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h new file mode 100644 index 00000000..76ee6fda --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h @@ -0,0 +1,30 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_PROMISE, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 25.4.5.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_PROMISE_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ROUTINE (LIT_MAGIC_STRING_THEN, ECMA_PROMISE_PROTOTYPE_ROUTINE_THEN, 2, 2) +ROUTINE (LIT_MAGIC_STRING_CATCH, ECMA_PROMISE_PROTOTYPE_ROUTINE_CATCH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FINALLY, ECMA_PROMISE_PROTOTYPE_ROUTINE_FINALLY, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.cpp new file mode 100644 index 00000000..02f600c5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.cpp @@ -0,0 +1,527 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-iterator-object.h" +#include "ecma-number-object.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_PROMISE_ROUTINE_START = 0, + ECMA_PROMISE_ROUTINE_REJECT, + ECMA_PROMISE_ROUTINE_RESOLVE, + ECMA_PROMISE_ROUTINE_RACE, + ECMA_PROMISE_ROUTINE_ALL, + ECMA_PROMISE_ROUTINE_ALLSETTLED, + ECMA_PROMISE_ROUTINE_ANY, + ECMA_PROMISE_ROUTINE_SPECIES_GET +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-promise.inc.h" +#define BUILTIN_UNDERSCORED_ID promise +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup promise ECMA Promise object built-in + * @{ + */ + +/** + * Runtime Semantics: PerformPromiseRace. + * + * See also: + * ES2020 25.6.4.4.1 + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +static inline ecma_value_t +ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for race */ + ecma_value_t next_method, /**< next method */ + ecma_object_t *capability_obj_p, /**< PromiseCapability record */ + ecma_value_t ctor, /**< Constructor value */ + bool *done_p) /**< [out] iteratorRecord[[done]] */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + JERRY_ASSERT (ecma_is_constructor (ctor)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (ctor), LIT_MAGIC_STRING_RESOLVE); + + if (ECMA_IS_VALUE_ERROR (resolve)) + { + return resolve; + } + + if (!ecma_op_is_callable (resolve)) + { + ecma_free_value (resolve); + return ecma_raise_type_error (ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE); + } + + ecma_object_t *resolve_func_p = ecma_get_object_from_value (resolve); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 5. */ + while (true) + { + /* a. */ + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + /* b, c. */ + if (ECMA_IS_VALUE_ERROR (next)) + { + goto done; + } + + /* d. */ + if (ecma_is_value_false (next)) + { + /* ii. */ + ret_value = ecma_copy_value (capability_p->header.u.cls.u3.promise); + goto done; + } + + /* e. */ + ecma_value_t next_val = ecma_op_iterator_value (next); + ecma_free_value (next); + + /* f, g. */ + if (ECMA_IS_VALUE_ERROR (next_val)) + { + goto done; + } + + /* h. */ + ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_val, 1); + ecma_free_value (next_val); + + if (ECMA_IS_VALUE_ERROR (next_promise)) + { + goto exit; + } + + /* i. */ + ecma_value_t args[2] = { capability_p->resolve, capability_p->reject }; + ecma_value_t result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); + ecma_free_value (next_promise); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + ecma_free_value (result); + } + +done: + *done_p = true; +exit: + ecma_deref_object (resolve_func_p); + + return ret_value; +} /* ecma_builtin_promise_perform_race */ + +/** + * Runtime Semantics: Perform Promise all, allSettled or any. + * + * See also: + * ES2020 25.6.4.1.1 + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +static inline ecma_value_t +ecma_builtin_promise_perform (ecma_value_t iterator, /**< iteratorRecord */ + ecma_value_t next_method, /**< next method */ + ecma_object_t *capability_obj_p, /**< PromiseCapability record */ + ecma_value_t ctor, /**< the caller of Promise.all */ + uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + bool *done_p) /**< [out] iteratorRecord[[done]] */ +{ + /* 1. - 2. */ + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + JERRY_ASSERT (ecma_is_constructor (ctor)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (ctor), LIT_MAGIC_STRING_RESOLVE); + + if (ECMA_IS_VALUE_ERROR (resolve)) + { + return resolve; + } + + if (!ecma_op_is_callable (resolve)) + { + ecma_free_value (resolve); + return ecma_raise_type_error (ECMA_ERR_RESOLVE_METHOD_MUST_BE_CALLABLE); + } + + ecma_object_t *resolve_func_p = ecma_get_object_from_value (resolve); + + /* 3. */ + ecma_object_t *values_array_obj_p = ecma_op_new_array_object (0); + ecma_value_t values_array = ecma_make_object_value (values_array_obj_p); + /* 4. */ + ecma_value_t remaining = ecma_op_create_number_object (ecma_make_integer_value (1)); + /* 5. */ + uint32_t idx = 0; + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 6. */ + while (true) + { + /* a. */ + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + /* b. - c. */ + if (ECMA_IS_VALUE_ERROR (next)) + { + goto done; + } + + /* d. */ + if (ecma_is_value_false (next)) + { + /* ii. - iii. */ + if (ecma_promise_remaining_inc_or_dec (remaining, false) == 0) + { + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_ANY) + { + ret_value = ecma_raise_aggregate_error (values_array, ECMA_VALUE_UNDEFINED); + goto done; + } + + /* 2. */ + ecma_value_t resolve_result = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &values_array, + 1); + /* 3. */ + if (ECMA_IS_VALUE_ERROR (resolve_result)) + { + goto done; + } + + ecma_free_value (resolve_result); + } + + /* iv. */ + ret_value = ecma_copy_value (capability_p->header.u.cls.u3.promise); + goto done; + } + + /* e. */ + ecma_value_t next_value = ecma_op_iterator_value (next); + ecma_free_value (next); + + /* f. - g. */ + if (ECMA_IS_VALUE_ERROR (next_value)) + { + goto done; + } + + /* h. */ + ecma_builtin_helper_def_prop_by_index (values_array_obj_p, + idx, + ECMA_VALUE_UNDEFINED, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + /* i. */ + ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_value, 1); + ecma_free_value (next_value); + + /* j. */ + if (ECMA_IS_VALUE_ERROR (next_promise)) + { + goto exit; + } + + if (JERRY_UNLIKELY (idx == UINT32_MAX - 1)) + { + ecma_raise_range_error (ECMA_ERR_PROMISE_ALL_REMAINING_ELEMENTS_LIMIT_REACHED); + goto exit; + } + + idx++; + ecma_value_t args[2]; + ecma_object_t *executor_func_p = NULL; + + if (builtin_routine_id != ECMA_PROMISE_ROUTINE_ANY) + { + /* k. */ + executor_func_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); + + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) executor_func_p; + + /* m. + t. */ + executor_p->index = idx; + + /* n. */ + executor_p->values = values_array; + + /* o. */ + executor_p->capability = ecma_make_object_value (capability_obj_p); + + /* p. */ + executor_p->remaining_elements = remaining; + + uint8_t executor_type = ECMA_PROMISE_ALL_RESOLVE << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_ALLSETTLED) + { + executor_type = ECMA_PROMISE_ALLSETTLED_RESOLVE << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + } + + executor_p->header.u.built_in.u2.routine_flags |= executor_type; + + args[0] = ecma_make_object_value (executor_func_p); + } + else + { + args[0] = capability_p->resolve; + } + + /* q. */ + ecma_promise_remaining_inc_or_dec (remaining, true); + ecma_value_t result; + + if (builtin_routine_id != ECMA_PROMISE_ROUTINE_ALL) + { + uint8_t executor_type = ECMA_PROMISE_ALLSETTLED_REJECT << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_ANY) + { + executor_type = ECMA_PROMISE_ANY_REJECT << ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT; + } + + ecma_object_t *reject_func_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); + + ecma_promise_all_executor_t *reject_p = (ecma_promise_all_executor_t *) reject_func_p; + reject_p->index = idx; + reject_p->values = values_array; + reject_p->capability = ecma_make_object_value (capability_obj_p); + reject_p->remaining_elements = remaining; + reject_p->header.u.built_in.u2.routine_flags |= executor_type; + args[1] = ecma_make_object_value (reject_func_p); + result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); + ecma_deref_object (reject_func_p); + } + else + { + args[1] = capability_p->reject; + result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); + } + + ecma_free_value (next_promise); + + if (builtin_routine_id != ECMA_PROMISE_ROUTINE_ANY) + { + ecma_deref_object (executor_func_p); + } + + /* s. */ + if (ECMA_IS_VALUE_ERROR (result)) + { + goto exit; + } + + ecma_free_value (result); + } + +done: + *done_p = true; +exit: + ecma_free_value (remaining); + ecma_deref_object (values_array_obj_p); + ecma_deref_object (resolve_func_p); + + return ret_value; +} /* ecma_builtin_promise_perform */ + +/** + * The common function for Promise.race, Promise.all, Promise.any and Promise.allSettled. + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_promise_helper (ecma_value_t this_arg, /**< 'this' argument */ + ecma_value_t iterable, /**< the items to be resolved */ + uint8_t builtin_routine_id) /**< built-in wide routine identifier */ +{ + ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg, ECMA_VALUE_UNDEFINED); + + if (JERRY_UNLIKELY (capability_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method); + ecma_value_t ret = ECMA_VALUE_ERROR; + + if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&iterator, capability_obj_p))) + { + ecma_free_value (next_method); + ecma_deref_object (capability_obj_p); + return iterator; + } + + bool is_done = false; + + if (builtin_routine_id == ECMA_PROMISE_ROUTINE_RACE) + { + ret = ecma_builtin_promise_perform_race (iterator, next_method, capability_obj_p, this_arg, &is_done); + } + else + { + ret = + ecma_builtin_promise_perform (iterator, next_method, capability_obj_p, this_arg, builtin_routine_id, &is_done); + } + + if (ECMA_IS_VALUE_ERROR (ret)) + { + if (!is_done) + { + ret = ecma_op_iterator_close (iterator); + } + + ecma_op_if_abrupt_reject_promise (&ret, capability_obj_p); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_deref_object (capability_obj_p); + + return ret; +} /* ecma_builtin_promise_helper */ + +/** + * Handle calling [[Call]] of built-in Promise object. + * + * ES2015 25.4.3 Promise is not intended to be called + * as a function and will throw an exception when called + * in that manner. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_promise_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_PROMISE_REQUIRES_NEW); +} /* ecma_builtin_promise_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Promise object. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_promise_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0 || !ecma_op_is_callable (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_FIRST_PARAMETER_MUST_BE_CALLABLE); + } + + return ecma_op_create_promise_object (arguments_list_p[0], + ECMA_VALUE_UNDEFINED, + JERRY_CONTEXT (current_new_target_p)); +} /* ecma_builtin_promise_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_promise_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + switch (builtin_routine_id) + { + case ECMA_PROMISE_ROUTINE_REJECT: + case ECMA_PROMISE_ROUTINE_RESOLVE: + { + bool is_resolve = (builtin_routine_id == ECMA_PROMISE_ROUTINE_RESOLVE); + return ecma_promise_reject_or_resolve (this_arg, arguments_list_p[0], is_resolve); + } + case ECMA_PROMISE_ROUTINE_RACE: + case ECMA_PROMISE_ROUTINE_ALL: + case ECMA_PROMISE_ROUTINE_ALLSETTLED: + case ECMA_PROMISE_ROUTINE_ANY: + { + return ecma_builtin_promise_helper (this_arg, arguments_list_p[0], builtin_routine_id); + } + case ECMA_PROMISE_ROUTINE_SPECIES_GET: + { + return ecma_copy_value (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_promise_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h new file mode 100644 index 00000000..6c697539 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Promose built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_PROMISE_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_REJECT, ECMA_PROMISE_ROUTINE_REJECT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RESOLVE, ECMA_PROMISE_ROUTINE_RESOLVE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_RACE, ECMA_PROMISE_ROUTINE_RACE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ALL, ECMA_PROMISE_ROUTINE_ALL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ALLSETTLED, ECMA_PROMISE_ROUTINE_ALLSETTLED, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ANY, ECMA_PROMISE_ROUTINE_ANY, 1, 1) + +/* ES2015 25.4.4.6 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ECMA_PROMISE_ROUTINE_SPECIES_GET, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.cpp new file mode 100644 index 00000000..2a2097d3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.cpp @@ -0,0 +1,160 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-proxy-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_PROXY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_PROXY_OBJECT_ROUTINE_START = 0, + ECMA_BUILTIN_PROXY_OBJECT_REVOCABLE, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-proxy.inc.h" +#define BUILTIN_UNDERSCORED_ID proxy +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup proxy ECMA Proxy object built-in + * @{ + */ + +/** + * The Proxy object's 'revocable' routine + * + * See also: + * ES2015 26.2.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_proxy_object_revocable (ecma_value_t target, /**< target argument */ + ecma_value_t handler) /**< handler argument */ +{ + ecma_object_t *rev_proxy_p = ecma_proxy_create_revocable (target, handler); + + if (JERRY_UNLIKELY (rev_proxy_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_object_value (rev_proxy_p); +} /* ecma_builtin_proxy_object_revocable */ + +/** + * Handle calling [[Call]] of built-in Proxy object + * + * See also: + * ES2015 26.2.2 + * + * @return raised error + */ +ecma_value_t +ecma_builtin_proxy_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + /* 1. */ + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_PROXY_REQUIRES_NEW); +} /* ecma_builtin_proxy_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in proxy object + * + * See also: + * ES2015 26.2.2 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * new proxy object - otherwise + */ +ecma_value_t +ecma_builtin_proxy_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + /* 2. */ + ecma_object_t *proxy_p = ecma_proxy_create (arguments_list_len > 0 ? arguments_list_p[0] : ECMA_VALUE_UNDEFINED, + arguments_list_len > 1 ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED, + 0); + + if (JERRY_UNLIKELY (proxy_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_object_value (proxy_p); +} /* ecma_builtin_proxy_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_proxy_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (this_arg, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_PROXY_OBJECT_REVOCABLE: + { + return ecma_builtin_proxy_object_revocable (arguments_list_p[0], arguments_list_p[1]); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_proxy_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_PROXY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h new file mode 100644 index 00000000..32670616 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Proxy object built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_PROXY + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 2, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_PROXY_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +ROUTINE (LIT_MAGIC_STRING_REVOCABLE, ECMA_BUILTIN_PROXY_OBJECT_REVOCABLE, 2, 2) + +#endif /* JERRY_BUILTIN_PROXY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.cpp new file mode 100644 index 00000000..f72ac2c2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-rangeerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID range_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h new file mode 100644 index 00000000..1307e4a0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RangeError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_RANGE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_RANGE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.cpp new file mode 100644 index 00000000..c17a2369 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-rangeerror.inc.h" +#define BUILTIN_UNDERSCORED_ID range_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup rangeerror ECMA RangeError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in RangeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_range_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_RANGE, arguments_list_p, arguments_list_len); +} /* ecma_builtin_range_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in RangeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_range_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_range_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_range_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h new file mode 100644 index 00000000..6891fa5b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RangeError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_RANGE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.cpp new file mode 100644 index 00000000..5212d6bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-referenceerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID reference_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h new file mode 100644 index 00000000..caa9e0e3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ReferenceError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_REFERENCE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_REFERENCE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.cpp new file mode 100644 index 00000000..2a3f2da5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-referenceerror.inc.h" +#define BUILTIN_UNDERSCORED_ID reference_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup referenceerror ECMA ReferenceError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in ReferenceError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_reference_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_REFERENCE, arguments_list_p, arguments_list_len); +} /* ecma_builtin_reference_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in ReferenceError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_reference_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_reference_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_reference_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h new file mode 100644 index 00000000..b28ada19 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ReferenceError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_REFERENCE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.cpp new file mode 100644 index 00000000..056a6b5f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.cpp @@ -0,0 +1,344 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" +#include "ecma-builtin-function-prototype.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-iterator-object.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_REFLECT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_REFLECT_OBJECT_ROUTINE_START = 0, + ECMA_REFLECT_OBJECT_GET, /* ECMA-262 v6, 26.1.6 */ + ECMA_REFLECT_OBJECT_SET, /* ECMA-262 v6, 26.1.13 */ + ECMA_REFLECT_OBJECT_HAS, /* ECMA-262 v6, 26.1.9 */ + ECMA_REFLECT_OBJECT_DELETE_PROPERTY, /* ECMA-262 v6, 26.1.4 */ + ECMA_REFLECT_OBJECT_CONSTRUCT, /* ECMA-262, 26.1.2 */ + ECMA_REFLECT_OBJECT_OWN_KEYS, /* ECMA-262 v6, 26.1.11 */ + ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.8 */ + ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.14 */ + ECMA_REFLECT_OBJECT_APPLY, /* ECMA-262 v6, 26.1.1 */ + ECMA_REFLECT_OBJECT_DEFINE_PROPERTY, /* ECMA-262 v6, 26.1.3 */ + ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR, /* ECMA-262 v6, 26.1.7 */ + ECMA_REFLECT_OBJECT_IS_EXTENSIBLE, /* ECMA-262 v6, 26.1.10 */ + ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS, /* ECMA-262 v6, 26.1.12 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-reflect.inc.h" +#define BUILTIN_UNDERSCORED_ID reflect +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup object ECMA Reflect object built-in + * @{ + */ + +/** + * Dispatcher for the built-in's routines. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + if (builtin_routine_id < ECMA_REFLECT_OBJECT_CONSTRUCT) + { + /* 1. */ + if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + /* 2. */ + ecma_string_t *name_str_p = ecma_op_to_property_key (arguments_list[1]); + + /* 3. */ + if (name_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value; + ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); + switch (builtin_routine_id) + { + case ECMA_REFLECT_OBJECT_GET: + { + ecma_value_t receiver = arguments_list[0]; + + /* 4. */ + if (arguments_number > 2) + { + receiver = arguments_list[2]; + } + + ret_value = ecma_op_object_get_with_receiver (target_p, name_str_p, receiver); + break; + } + + case ECMA_REFLECT_OBJECT_HAS: + { + ret_value = ecma_op_object_has_property (target_p, name_str_p); + break; + } + + case ECMA_REFLECT_OBJECT_DELETE_PROPERTY: + { + ret_value = ecma_op_object_delete (target_p, name_str_p, false); + break; + } + + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_SET); + + ecma_value_t receiver = arguments_list[0]; + + if (arguments_number > 3) + { + receiver = arguments_list[3]; + } + + ret_value = ecma_op_object_put_with_receiver (target_p, name_str_p, arguments_list[2], receiver, false); + break; + } + } + + ecma_deref_ecma_string (name_str_p); + return ret_value; + } + + if (builtin_routine_id == ECMA_REFLECT_OBJECT_OWN_KEYS) + { + /* 1. */ + if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); + + /* 2. */ + ecma_collection_t *prop_names = ecma_op_object_own_property_keys (target_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (prop_names == NULL) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 3. */ + return ecma_op_new_array_object_from_collection (prop_names, false); + } + + if (builtin_routine_id == ECMA_REFLECT_OBJECT_CONSTRUCT) + { + /* 1. */ + if (arguments_number < 1 || !ecma_is_constructor (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR); + } + + ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); + + /* 2. */ + ecma_object_t *new_target_p = target_p; + + if (arguments_number > 2) + { + /* 3. */ + if (!ecma_is_constructor (arguments_list[2])) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_A_CONSTRUCTOR); + } + + new_target_p = ecma_get_object_from_value (arguments_list[2]); + } + + /* 4. */ + if (arguments_number < 2) + { + return ecma_raise_type_error (ECMA_ERR_REFLECT_EXPECTS_AN_OBJECT_AS_SECOND_ARGUMENT); + } + + ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], false); + + if (coll_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value = ecma_op_function_construct (target_p, new_target_p, coll_p->buffer_p, coll_p->item_count); + + ecma_collection_free (coll_p); + return ret_value; + } + + if (!ecma_is_value_object (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + } + + switch (builtin_routine_id) + { + case ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF: + { + return ecma_builtin_object_object_get_prototype_of (ecma_get_object_from_value (arguments_list[0])); + } + case ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF: + { + if (!ecma_is_value_object (arguments_list[1]) && !ecma_is_value_null (arguments_list[1])) + { + return ecma_raise_type_error (ECMA_ERR_PROTOTYPE_IS_NEITHER_OBJECT_NOR_NULL); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + ecma_value_t status; + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + status = ecma_proxy_object_set_prototype_of (obj_p, arguments_list[1]); + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + status = ecma_op_ordinary_object_set_prototype_of (obj_p, arguments_list[1]); + } + + return status; + } + case ECMA_REFLECT_OBJECT_APPLY: + { + if (!ecma_op_is_callable (arguments_list[0])) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION); + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (arguments_list[0]); + return ecma_builtin_function_prototype_object_apply (func_obj_p, arguments_list[1], arguments_list[2]); + } + case ECMA_REFLECT_OBJECT_DEFINE_PROPERTY: + { + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + ecma_string_t *name_str_p = ecma_op_to_property_key (arguments_list[1]); + + if (name_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_property_descriptor_t prop_desc; + ecma_value_t conv_result = ecma_op_to_property_descriptor (arguments_list[2], &prop_desc); + + if (ECMA_IS_VALUE_ERROR (conv_result)) + { + ecma_deref_ecma_string (name_str_p); + return conv_result; + } + + ecma_value_t result = ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc); + + ecma_deref_ecma_string (name_str_p); + ecma_free_property_descriptor (&prop_desc); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + bool boolean_result = ecma_op_to_boolean (result); + + return ecma_make_boolean_value (boolean_result); + } + case ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR: + { + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + ecma_string_t *name_str_p = ecma_op_to_property_key (arguments_list[1]); + + if (name_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_val = ecma_builtin_object_object_get_own_property_descriptor (obj_p, name_str_p); + ecma_deref_ecma_string (name_str_p); + return ret_val; + } + case ECMA_REFLECT_OBJECT_IS_EXTENSIBLE: + { + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + return ecma_builtin_object_object_is_extensible (obj_p); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS); + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_prevent_extensions (obj_p); + } +#endif /* !JERRY_BUILTIN_PROXY */ + + ecma_op_ordinary_object_prevent_extensions (obj_p); + + return ECMA_VALUE_TRUE; + } + } +} /* ecma_builtin_reflect_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REFLECT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.inc.h new file mode 100644 index 00000000..4f4c824a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_REFLECT + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_APPLY, ECMA_REFLECT_OBJECT_APPLY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, ECMA_REFLECT_OBJECT_DEFINE_PROPERTY, 3, 3) +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR, 2, 2) +ROUTINE (LIT_MAGIC_STRING_GET, ECMA_REFLECT_OBJECT_GET, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_REFLECT_OBJECT_SET, NON_FIXED, 3) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_REFLECT_OBJECT_HAS, 2, 2) +ROUTINE (LIT_MAGIC_STRING_DELETE_PROPERTY_UL, ECMA_REFLECT_OBJECT_DELETE_PROPERTY, 2, 2) +ROUTINE (LIT_MAGIC_STRING_OWN_KEYS_UL, ECMA_REFLECT_OBJECT_OWN_KEYS, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_CONSTRUCT, ECMA_REFLECT_OBJECT_CONSTRUCT, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_EXTENSIBLE, ECMA_REFLECT_OBJECT_IS_EXTENSIBLE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL, ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF, 2, 2) + +#endif /* JERRY_BUILTIN_REFLECT */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp new file mode 100644 index 00000000..94c0384d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp @@ -0,0 +1,659 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-regexp-object.h" + +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_REGEXP +#include "ecma-regexp-object.h" + +#include "re-compiler.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID regexp_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup regexpprototype ECMA RegExp.prototype object built-in + * @{ + */ + +/** + * Helper function to retrieve the flags associated with a RegExp object + * + * @return ECMA_VALUE_{TRUE,FALSE} depends on whether the given flag is present. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_flags_helper (ecma_extended_object_t *re_obj_p, /**< this object */ + uint16_t builtin_routine_id) /**< id of the flag */ +{ + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, re_obj_p->u.cls.u3.value); + + uint16_t flags = bc_p->header.status_flags; + + static const uint8_t re_flags[] = { + RE_FLAG_GLOBAL, RE_FLAG_IGNORE_CASE, RE_FLAG_MULTILINE, RE_FLAG_STICKY, RE_FLAG_UNICODE, RE_FLAG_DOTALL, + }; + + uint16_t offset = (uint16_t) (builtin_routine_id - ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL); + return ecma_make_boolean_value ((flags & re_flags[offset]) != 0); +} /* ecma_builtin_regexp_prototype_flags_helper */ + +/** + * The RegExp.prototype object's 'flags' accessor property + * + * See also: + * ECMA-262 v6, 21.2.5.3 + * + * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object + * string value - otherwise + * + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_get_flags (ecma_object_t *object_p) /**< this object */ +{ + static const lit_magic_string_id_t flag_lit_ids[] = { LIT_MAGIC_STRING_GLOBAL, LIT_MAGIC_STRING_IGNORECASE_UL, + LIT_MAGIC_STRING_MULTILINE, LIT_MAGIC_STRING_DOTALL, + LIT_MAGIC_STRING_UNICODE, LIT_MAGIC_STRING_STICKY }; + + static const lit_utf8_byte_t flag_chars[] = { LIT_CHAR_LOWERCASE_G, LIT_CHAR_LOWERCASE_I, LIT_CHAR_LOWERCASE_M, + LIT_CHAR_LOWERCASE_S, LIT_CHAR_LOWERCASE_U, LIT_CHAR_LOWERCASE_Y }; + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + for (uint32_t i = 0; i < sizeof (flag_lit_ids) / sizeof (lit_magic_string_id_t); i++) + { + ecma_value_t result = ecma_op_object_get_by_magic_id (object_p, flag_lit_ids[i]); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_stringbuilder_destroy (&builder); + return result; + } + + if (ecma_op_to_boolean (result)) + { + ecma_stringbuilder_append_byte (&builder, flag_chars[i]); + } + + ecma_free_value (result); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_regexp_prototype_get_flags */ + +/** + * The EscapeRegExpPattern method. + * + * See also: + * ECMA-262 v6, 21.2.3.2.4 + * + * @return ecma_value_t + */ +static ecma_value_t +ecma_op_escape_regexp_pattern (ecma_string_t *pattern_str_p) /**< RegExp pattern */ +{ + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + ECMA_STRING_TO_UTF8_STRING (pattern_str_p, pattern_start_p, pattern_start_size); + + const lit_utf8_byte_t *pattern_str_curr_p = pattern_start_p; + const lit_utf8_byte_t *pattern_str_end_p = pattern_start_p + pattern_start_size; + + while (pattern_str_curr_p < pattern_str_end_p) + { + ecma_char_t c = lit_cesu8_read_next (&pattern_str_curr_p); + + switch (c) + { + case LIT_CHAR_SLASH: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\/", 2); + break; + } + case LIT_CHAR_LF: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\n", 2); + break; + } + case LIT_CHAR_CR: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\r", 2); + break; + } + case LIT_CHAR_LS: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2028", 6); + break; + } + case LIT_CHAR_PS: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2029", 6); + break; + } + case LIT_CHAR_BACKSLASH: + { + JERRY_ASSERT (pattern_str_curr_p < pattern_str_end_p); + ecma_stringbuilder_append_char (&builder, LIT_CHAR_BACKSLASH); + ecma_stringbuilder_append_char (&builder, lit_cesu8_read_next (&pattern_str_curr_p)); + break; + } + default: + { + ecma_stringbuilder_append_char (&builder, c); + break; + } + } + } + + ECMA_FINALIZE_UTF8_STRING (pattern_start_p, pattern_start_size); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_op_escape_regexp_pattern */ + +/** + * The RegExp.prototype object's 'source' accessor property + * + * See also: + * ECMA-262 v6, 21.2.5.10 + * + * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object + * string value - otherwise + * + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_get_source (ecma_extended_object_t *re_obj_p) /**< this argument */ +{ + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, re_obj_p->u.cls.u3.value); + + return ecma_op_escape_regexp_pattern (ecma_get_string_from_value (bc_p->source)); +} /* ecma_builtin_regexp_prototype_get_source */ + +#if JERRY_BUILTIN_ANNEXB +/** + * The RegExp.prototype object's 'compile' routine + * + * See also: + * ECMA-262 v11, B.2.5.1 + * + * @return undefined - if compiled successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this */ + ecma_value_t pattern_arg, /**< pattern or RegExp object */ + ecma_value_t flags_arg) /**< flags */ +{ + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) this_obj_p; + re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, re_obj_p->u.cls.u3.value); + + ecma_value_t ret_value; + + if (ecma_object_is_regexp_object (pattern_arg)) + { + if (!ecma_is_value_undefined (flags_arg)) + { + return ecma_raise_type_error (ECMA_ERR_INVALID_ARGUMENT); + } + + ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_arg); + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, pattern_obj_p->u.cls.u3.value); + + ret_value = ecma_op_create_regexp_from_bytecode (this_obj_p, bc_p); + } + else + { + ret_value = ecma_op_create_regexp_from_pattern (this_obj_p, pattern_arg, flags_arg); + } + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_value_t status = ecma_builtin_helper_def_prop (this_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + ECMA_PROPERTY_FLAG_WRITABLE | JERRY_PROP_SHOULD_THROW); + + ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + ecma_ref_object (this_obj_p); + } + + return ret_value; +} /* ecma_builtin_regexp_prototype_compile */ + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * The RegExp.prototype object's 'exec' routine + * + * See also: + * ECMA-262 v5, 15.10.6.2 + * + * @return array object containing the results - if the matched + * null - otherwise + * + * May raise error, so returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + ecma_value_t obj_this = ecma_op_to_object (this_arg); + if (ECMA_IS_VALUE_ERROR (obj_this)) + { + return obj_this; + } + + ecma_string_t *input_str_p = ecma_op_to_string (arg); + if (JERRY_UNLIKELY (input_str_p == NULL)) + { + ecma_free_value (obj_this); + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret_value = ecma_regexp_exec_helper (ecma_get_object_from_value (obj_this), input_str_p); + + ecma_free_value (obj_this); + ecma_deref_ecma_string (input_str_p); + + return ret_value; +} /* ecma_builtin_regexp_prototype_exec */ + +/** + * The RegExp.prototype object's 'test' routine + * + * See also: + * ECMA-262 v5, 15.10.6.3 + * ECMA-262 v6, 21.2.5.13 + * + * @return true - if match is not null + * false - otherwise + * + * May raise error, so returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_test (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + ecma_string_t *arg_str_p = ecma_op_to_string (arg); + + if (JERRY_UNLIKELY (arg_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_op_regexp_exec (this_arg, arg_str_p); + + ecma_deref_ecma_string (arg_str_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_value_t ret_value = ecma_make_boolean_value (!ecma_is_value_null (result)); + ecma_free_value (result); + + return ret_value; +} /* ecma_builtin_regexp_prototype_test */ + +/** + * The RegExp.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v5, 15.10.6.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_regexp_prototype_to_string (ecma_object_t *object_p) /**< this object */ +{ + ecma_value_t result = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_SOURCE); + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_string_t *source_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (source_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + result = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_FLAGS); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_ecma_string (source_p); + return result; + } + + ecma_string_t *flags_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (flags_p == NULL) + { + ecma_deref_ecma_string (source_p); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_SLASH); + ecma_stringbuilder_append (&builder, source_p); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_SLASH); + ecma_stringbuilder_append (&builder, flags_p); + + ecma_deref_ecma_string (source_p); + ecma_deref_ecma_string (flags_p); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_regexp_prototype_to_string */ + +/** + * The RegExp.prototype object's 'matchAll' routine + * + * See also: + * ECMA-262 v11, 21.2.5.8 + * + * @return ecma_value_t + */ +static ecma_value_t +ecma_builtin_regexp_prototype_match_all (ecma_object_t *regexp_obj_p, /**< this argument */ + ecma_value_t string_arg) /**< source string */ +{ + /* 3. */ + ecma_string_t *str_p = ecma_op_to_string (string_arg); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 4. */ + ecma_value_t constructor = ecma_op_species_constructor (regexp_obj_p, ECMA_BUILTIN_ID_REGEXP); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + ecma_deref_ecma_string (str_p); + return constructor; + } + + /* 5. */ + ecma_value_t get_flag = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (get_flag)) + { + ecma_deref_ecma_string (str_p); + ecma_free_value (constructor); + return get_flag; + } + + ecma_string_t *flags = ecma_op_to_string (get_flag); + + ecma_free_value (get_flag); + + if (JERRY_UNLIKELY (flags == NULL)) + { + ecma_deref_ecma_string (str_p); + ecma_free_value (constructor); + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + ecma_value_t flags_value = ecma_make_string_value (flags); + ecma_value_t match_args[] = { ecma_make_object_value (regexp_obj_p), flags_value }; + ecma_value_t matcher = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, match_args, 2); + + ecma_deref_object (constructor_obj_p); + + if (ECMA_IS_VALUE_ERROR (matcher)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + return matcher; + } + + /* 7. */ + ecma_value_t get_last_index = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + if (ECMA_IS_VALUE_ERROR (get_last_index)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + ecma_free_value (matcher); + return get_last_index; + } + + ecma_length_t last_index; + ecma_value_t to_len = ecma_op_to_length (get_last_index, &last_index); + + ecma_free_value (get_last_index); + + if (ECMA_IS_VALUE_ERROR (to_len)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + ecma_free_value (matcher); + return to_len; + } + + /* 8. */ + ecma_object_t *matcher_obj_p = ecma_get_object_from_value (matcher); + ecma_value_t last_index_value = ecma_make_length_value (last_index); + ecma_value_t set = + ecma_op_object_put (matcher_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index_value, true); + + ecma_free_value (last_index_value); + + if (ECMA_IS_VALUE_ERROR (set)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_ecma_string (flags); + ecma_deref_object (matcher_obj_p); + } + + uint16_t parsed_flag; + ecma_value_t flag_parse = ecma_regexp_parse_flags (flags, &parsed_flag); + + ecma_deref_ecma_string (flags); + + if (ECMA_IS_VALUE_ERROR (flag_parse)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_object (matcher_obj_p); + return flag_parse; + } + + /* 13. */ + ecma_object_t *result_obj; + ecma_object_t *proto_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_STRING_ITERATOR_PROTOTYPE); + result_obj = ecma_create_object (proto_p, sizeof (ecma_regexp_string_iterator_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) result_obj; + ext_obj_p->u.cls.type = ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR; + ext_obj_p->u.cls.u1.regexp_string_iterator_flags = (uint8_t) (parsed_flag & (RE_FLAG_GLOBAL | RE_FLAG_UNICODE)); + + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) result_obj; + + regexp_string_iterator_obj->iterating_regexp = matcher; + regexp_string_iterator_obj->iterated_string = ecma_make_string_value (str_p); + + ecma_deref_object (matcher_obj_p); + + return ecma_make_object_value (result_obj); +} /* ecma_builtin_regexp_prototype_match_all */ + +/** + * Dispatcher of the Regexp built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_regexp_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + ecma_object_t *obj_p = NULL; + + /* 1. && 2. */ + if (ecma_is_value_object (this_arg)) + { + obj_p = ecma_get_object_from_value (this_arg); + + if (builtin_routine_id < ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST + && !ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + obj_p = NULL; + } + } + + if (obj_p == NULL) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + switch (builtin_routine_id) + { +#if JERRY_BUILTIN_ANNEXB + case ECMA_REGEXP_PROTOTYPE_ROUTINE_COMPILE: + { + return ecma_builtin_regexp_prototype_compile (this_arg, arguments_list_p[0], arguments_list_p[1]); + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST: + { + return ecma_builtin_regexp_prototype_test (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC: + { + return ecma_builtin_regexp_prototype_exec (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_TO_STRING: + { + return ecma_builtin_regexp_prototype_to_string (obj_p); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SEARCH: + { + return ecma_regexp_search_helper (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH: + { + return ecma_regexp_match_helper (this_arg, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL: + { + return ecma_builtin_regexp_prototype_match_all (obj_p, arguments_list_p[0]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE: + { + return ecma_regexp_replace_helper (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT: + { + return ecma_regexp_split_helper (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_FLAGS: + { + return ecma_builtin_regexp_prototype_get_flags (obj_p); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_SOURCE: + { + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP); + } + + ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) obj_p; + return ecma_builtin_regexp_prototype_get_source (re_obj_p); + } + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_IGNORE_CASE: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_MULTILINE: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_STICKY: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_UNICODE: + case ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_DOT_ALL: + { + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_REGEXP); + } + + ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) obj_p; + return ecma_builtin_regexp_prototype_flags_helper (re_obj_p, builtin_routine_id); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_regexp_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h new file mode 100644 index 00000000..51486e9f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h @@ -0,0 +1,64 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RegExp.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_REGEXP + +/* ECMA-262 v5, 15.10.6.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_REGEXP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_FLAGS, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_FLAGS, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_SOURCE, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_SOURCE, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_GLOBAL, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_GLOBAL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_IGNORECASE_UL, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_IGNORE_CASE, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_DOTALL, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_DOT_ALL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_MULTILINE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_MULTILINE, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_UNICODE, + ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_UNICODE, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_STICKY, ECMA_REGEXP_PROTOTYPE_ROUTINE_GET_STICKY, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +ROUTINE (LIT_GLOBAL_SYMBOL_REPLACE, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE, 2, 2) +ROUTINE (LIT_GLOBAL_SYMBOL_SEARCH, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SEARCH, 1, 1) +ROUTINE (LIT_GLOBAL_SYMBOL_SPLIT, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT, 2, 2) +ROUTINE (LIT_GLOBAL_SYMBOL_MATCH, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH, 1, 1) +ROUTINE (LIT_GLOBAL_SYMBOL_MATCH_ALL, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL, 1, 1) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_COMPILE, ECMA_REGEXP_PROTOTYPE_ROUTINE_COMPILE, 2, 2) +#endif /* JERRY_BUILTIN_ANNEXB */ +ROUTINE (LIT_MAGIC_STRING_EXEC, ECMA_REGEXP_PROTOTYPE_ROUTINE_EXEC, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TEST, ECMA_REGEXP_PROTOTYPE_ROUTINE_TEST, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_REGEXP_PROTOTYPE_ROUTINE_TO_STRING, 0, 0) + +#endif /* JERRY_BUILTIN_REGEXP */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.cpp new file mode 100644 index 00000000..5a1d554d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.cpp @@ -0,0 +1,184 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-gc.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp-string-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID regexp_string_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %regexpstringiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in + * @{ + */ + +/** + * The %RegExpStringIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v11, 21.2.7.1.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_regexp_string_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + /* 2. */ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + + /* 3. */ + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) obj_p; + + /* 4. */ + if (ecma_is_value_empty (regexp_string_iterator_obj->iterated_string)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + /* 5. */ + ecma_value_t regexp = regexp_string_iterator_obj->iterating_regexp; + + /* 6. */ + ecma_value_t matcher_str_value = regexp_string_iterator_obj->iterated_string; + ecma_string_t *matcher_str_p = ecma_get_string_from_value (matcher_str_value); + + /* 9. */ + ecma_value_t match = ecma_op_regexp_exec (regexp, matcher_str_p); + + if (ECMA_IS_VALUE_ERROR (match)) + { + return match; + } + + /* 10. */ + if (ecma_is_value_null (match)) + { + ecma_free_value (regexp_string_iterator_obj->iterated_string); + regexp_string_iterator_obj->iterated_string = ECMA_VALUE_EMPTY; + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + ecma_object_t *match_result_array_p = ecma_get_object_from_value (match); + + ecma_value_t result = ECMA_VALUE_ERROR; + + /* 11. */ + if (regexp_string_iterator_obj->header.u.cls.u1.regexp_string_iterator_flags & RE_FLAG_GLOBAL) + { + ecma_value_t matched_str_value = ecma_op_object_get_by_index (match_result_array_p, 0); + + if (ECMA_IS_VALUE_ERROR (matched_str_value)) + { + goto free_variables; + } + + ecma_string_t *matched_str_p = ecma_op_to_string (matched_str_value); + + ecma_free_value (matched_str_value); + + if (JERRY_UNLIKELY (matched_str_p == NULL)) + { + goto free_variables; + } + + if (ecma_string_is_empty (matched_str_p)) + { + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp); + + ecma_value_t get_last_index = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + if (ECMA_IS_VALUE_ERROR (get_last_index)) + { + goto free_variables; + } + + ecma_length_t this_index; + ecma_value_t to_len = ecma_op_to_length (get_last_index, &this_index); + + ecma_free_value (get_last_index); + + if (ECMA_IS_VALUE_ERROR (to_len)) + { + goto free_variables; + } + + uint8_t flags = regexp_string_iterator_obj->header.u.cls.u1.regexp_string_iterator_flags; + ecma_length_t next_index = + ecma_op_advance_string_index (matcher_str_p, this_index, (flags & RE_FLAG_UNICODE) != 0); + + ecma_value_t next_index_value = ecma_make_length_value (next_index); + ecma_value_t set = ecma_op_object_put (regexp_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + next_index_value, + true); + + ecma_free_value (next_index_value); + + if (ECMA_IS_VALUE_ERROR (set)) + { + goto free_variables; + } + } + else + { + ecma_deref_ecma_string (matched_str_p); + } + } + else + { + ecma_free_value (regexp_string_iterator_obj->iterated_string); + regexp_string_iterator_obj->iterated_string = ECMA_VALUE_EMPTY; + } + + result = ecma_create_iter_result_object (match, ECMA_VALUE_FALSE); + +free_variables: + ecma_deref_object (match_result_array_p); + + return result; +} /* ecma_builtin_regexp_string_iterator_prototype_object_next */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h new file mode 100644 index 00000000..612bf697 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h @@ -0,0 +1,30 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %RegExpStringIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ecma_builtin_regexp_string_iterator_prototype_object_next, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.cpp new file mode 100644 index 00000000..0b3cfe58 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.cpp @@ -0,0 +1,217 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-regexp-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_REGEXP + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp.inc.h" +#define BUILTIN_UNDERSCORED_ID regexp +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup regexp ECMA RegExp object built-in + * @{ + */ + +static ecma_value_t +ecma_builtin_regexp_dispatch_helper (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_value_t pattern_value = ECMA_VALUE_UNDEFINED; + ecma_value_t flags_value = ECMA_VALUE_UNDEFINED; + bool create_regexp_from_bc = false; + bool free_arguments = false; + ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (arguments_list_len > 0) + { + /* pattern string or RegExp object */ + pattern_value = arguments_list_p[0]; + + if (arguments_list_len > 1) + { + flags_value = arguments_list_p[1]; + } + } + + ecma_value_t regexp_value = ecma_op_is_regexp (pattern_value); + + if (ECMA_IS_VALUE_ERROR (regexp_value)) + { + return regexp_value; + } + + bool pattern_is_regexp = regexp_value == ECMA_VALUE_TRUE; + re_compiled_code_t *bc_p = NULL; + + if (new_target_p == NULL) + { + new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP); + + if (pattern_is_regexp && ecma_is_value_undefined (flags_value)) + { + ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value); + + ecma_value_t pattern_constructor = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_CONSTRUCTOR); + + if (ECMA_IS_VALUE_ERROR (pattern_constructor)) + { + return pattern_constructor; + } + + bool is_same = ecma_op_same_value (ecma_make_object_value (new_target_p), pattern_constructor); + ecma_free_value (pattern_constructor); + + if (is_same) + { + return ecma_copy_value (pattern_value); + } + } + } + + if (ecma_object_is_regexp_object (pattern_value)) + { + ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_value); + bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, pattern_obj_p->u.cls.u3.value); + + create_regexp_from_bc = ecma_is_value_undefined (flags_value); + + if (!create_regexp_from_bc) + { + pattern_value = bc_p->source; + } + } + else if (pattern_is_regexp) + { + ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value); + + pattern_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_SOURCE); + + if (ECMA_IS_VALUE_ERROR (pattern_value)) + { + return pattern_value; + } + + if (ecma_is_value_undefined (flags_value)) + { + flags_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (flags_value)) + { + ecma_free_value (pattern_value); + return flags_value; + } + } + else + { + flags_value = ecma_copy_value (flags_value); + } + + free_arguments = true; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_object_t *new_target_obj_p = ecma_op_regexp_alloc (new_target_p); + + if (JERRY_LIKELY (new_target_obj_p != NULL)) + { + if (create_regexp_from_bc) + { + ret_value = ecma_op_create_regexp_from_bytecode (new_target_obj_p, bc_p); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (ret_value)); + } + else + { + ret_value = ecma_op_create_regexp_from_pattern (new_target_obj_p, pattern_value, flags_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_target_obj_p); + } + } + } + + if (free_arguments) + { + ecma_free_value (pattern_value); + ecma_free_value (flags_value); + } + + return ret_value; +} /* ecma_builtin_regexp_dispatch_helper */ + +/** + * Handle calling [[Call]] of built-in RegExp object + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_regexp_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_regexp_dispatch_helper (arguments_list_p, arguments_list_len); +} /* ecma_builtin_regexp_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in RegExp object + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_regexp_dispatch_helper (arguments_list_p, arguments_list_len); +} /* ecma_builtin_regexp_dispatch_construct */ + +/** + * 21.2.4.2 get RegExp [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_regexp_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_regexp_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h new file mode 100644 index 00000000..a9fa8922 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RegExp built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_REGEXP + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 2, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* ECMA-262 v5, 15.10.5.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_REGEXP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 21.2.4.2 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_regexp_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_REGEXP */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.cpp new file mode 100644 index 00000000..e435626b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.cpp @@ -0,0 +1,106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-set-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID set_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %setiteratorprototype% ECMA %SetIteratorPrototype% object built-in + * @{ + */ + +/** + * The %SetIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 23.2.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_set_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + return ecma_op_container_iterator_next (this_val, ECMA_OBJECT_CLASS_SET_ITERATOR); +} /* ecma_builtin_set_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_set_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + *routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_OBJECT_NEXT: + { + return ecma_builtin_set_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_set_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h new file mode 100644 index 00000000..4704236a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h @@ -0,0 +1,32 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %SetIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SET_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_BUILTIN_SET_ITERATOR_PROTOTYPE_OBJECT_NEXT, 0, 0) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.cpp new file mode 100644 index 00000000..8ff2687c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.cpp @@ -0,0 +1,65 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-set-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID set_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup set ECMA Set object built-in + * @{ + */ +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_set_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_SET_UL); +} /* ecma_builtin_set_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.inc.h new file mode 100644 index 00000000..8c6f874b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set-prototype.inc.h @@ -0,0 +1,55 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Set.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.2.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.1.3.13 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_CLEAR, ECMA_CONTAINER_ROUTINE_CLEAR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_ADD, ECMA_CONTAINER_ROUTINE_ADD, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_CONTAINER_ROUTINE_FOREACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_CONTAINER_ROUTINE_ENTRIES, 0, 0) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_KEYS, + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_SIZE, ECMA_CONTAINER_ROUTINE_SIZE_GETTER, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.cpp new file mode 100644 index 00000000..d875fdaf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.cpp @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-set.inc.h" +#define BUILTIN_UNDERSCORED_ID set +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup set ECMA Set object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Set object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_set_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_SET_REQUIRES_NEW); +} /* ecma_builtin_set_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Map object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_set_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_SET_UL, + ECMA_BUILTIN_ID_SET_PROTOTYPE); +} /* ecma_builtin_set_dispatch_construct */ + +/** + * 23.2.2.2 get Set [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_set_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_set_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.inc.h new file mode 100644 index 00000000..559b4ccb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-set.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Set built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.2.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.2.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SET_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 23.2.2.2 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_set_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.cpp new file mode 100644 index 00000000..321c2c82 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.cpp @@ -0,0 +1,113 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" + +#include "jrt-libc-includes.h" +#include "jrt.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-shared-arraybuffer-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID shared_arraybuffer_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup sharedarraybufferprototype ECMA SharedArrayBuffer.prototype object built-in + * @{ + */ + +/** + * The SharedArrayBuffer.prototype.bytelength accessor + * + * See also: + * ES11, 24.2.4.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_shared_arraybuffer_prototype_bytelength_getter (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)) + { + uint32_t len = ecma_arraybuffer_get_length (object_p); + + return ecma_make_uint32_value (len); + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER); +} /* ecma_builtin_shared_arraybuffer_prototype_bytelength_getter */ + +/** + * The SharedArrayBuffer.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v11, 24.2.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_shared_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number) /**< number of arguments */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + /* 2. */ + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER_OBJECT); + } + + return ecma_builtin_arraybuffer_slice (this_arg, argument_list_p, arguments_number); +} /* ecma_builtin_shared_arraybuffer_prototype_object_slice */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.inc.h new file mode 100644 index 00000000..c7b0b9eb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer-prototype.inc.h @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SharedArrayBuffer.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Readonly accessor properties */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ecma_builtin_shared_arraybuffer_prototype_bytelength_getter, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v11, 24.2.4.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_shared_arraybuffer_prototype_object_slice, NON_FIXED, 2) + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.cpp new file mode 100644 index 00000000..38fc8f12 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.cpp @@ -0,0 +1,96 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-dataview-object.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-shared-arraybuffer.inc.h" +#define BUILTIN_UNDERSCORED_ID shared_arraybuffer +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup sharedarraybuffer ECMA SharedArrayBuffer object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in SharedArrayBuffer object + * + * ES11 24.2.2 SharedArrayBuffer is not intended to be called as + * a function and will throw an exception when called in + * that manner. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_shared_arraybuffer_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_SHAREDARRAYBUFFER_REQUIRES_NEW); +} /* ecma_builtin_shared_arraybuffer_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in SharedArrayBuffer object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_shared_arraybuffer_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_shared_arraybuffer_object (arguments_list_p, arguments_list_len); +} /* ecma_builtin_shared_arraybuffer_dispatch_construct */ + +/** + * 24.2.3.2 get SharedArrayBuffer [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_shared_arraybuffer_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_shared_arraybuffer_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.inc.h new file mode 100644 index 00000000..8a7c73a7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-shared-arraybuffer.inc.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SharedArrayBuffer built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +/* ES11 24.1.3.3 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, + ecma_builtin_shared_arraybuffer_species_get, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.cpp new file mode 100644 index 00000000..5f2158cf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.cpp @@ -0,0 +1,205 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_ROUTINE_START = 0, + ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_OBJECT_NEXT, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-string-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID string_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %stringiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in + * @{ + */ + +/** + * The %StringIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 22.1.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_string_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + /* 1 - 2. */ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + /* 3. */ + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_STRING_ITERATOR)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + /* 4 - 5 */ + if (ecma_is_value_empty (iterated_value)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + JERRY_ASSERT (ecma_is_value_string (iterated_value)); + + ecma_string_t *string_p = ecma_get_string_from_value (iterated_value); + + /* 6. */ + lit_utf8_size_t position = ext_obj_p->u.cls.u2.iterator_index; + + if (JERRY_UNLIKELY (position == ECMA_ITERATOR_INDEX_LIMIT)) + { + /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] + property is stored as an internal property */ + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_value_t position_value = ecma_op_object_get (obj_p, prop_name_p); + + position = (lit_utf8_size_t) (ecma_get_number_from_value (position_value)); + ecma_free_value (position_value); + } + + /* 7. */ + lit_utf8_size_t len = ecma_string_get_length (string_p); + + /* 8. */ + if (position >= len) + { + ecma_deref_ecma_string (string_p); + ext_obj_p->u.cls.u3.iterated_value = ECMA_VALUE_EMPTY; + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + /* 9. */ + ecma_char_t first = ecma_string_get_char_at_pos (string_p, position); + + ecma_string_t *result_str_p; + lit_utf8_size_t result_size = 1; + + /* 10. */ + if (first < LIT_UTF16_HIGH_SURROGATE_MIN || first > LIT_UTF16_HIGH_SURROGATE_MAX || (position + 1 == len)) + { + result_str_p = ecma_new_ecma_string_from_code_unit (first); + } + /* 11. */ + else + { + /* 11.a */ + ecma_char_t second = ecma_string_get_char_at_pos (string_p, position + 1); + + /* 11.b */ + if (second < LIT_UTF16_LOW_SURROGATE_MIN || second > LIT_UTF16_LOW_SURROGATE_MAX) + { + result_str_p = ecma_new_ecma_string_from_code_unit (first); + } + /* 11.c */ + else + { + result_str_p = ecma_new_ecma_string_from_code_units (first, second); + result_size = 2; + } + } + + /* 13. */ + if (position + result_size < ECMA_ITERATOR_INDEX_LIMIT) + { + ext_obj_p->u.cls.u2.iterator_index = (uint16_t) (position + result_size); + } + else + { + ext_obj_p->u.cls.u2.iterator_index = ECMA_ITERATOR_INDEX_LIMIT; + + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_value_t put_result = + ecma_op_object_put (obj_p, prop_name_p, ecma_make_length_value (position + result_size), true); + + JERRY_ASSERT (ecma_is_value_true (put_result)); + } + + /* 14. */ + ecma_value_t result = ecma_create_iter_result_object (ecma_make_string_value (result_str_p), ECMA_VALUE_FALSE); + ecma_deref_ecma_string (result_str_p); + + return result; +} /* ecma_builtin_string_iterator_prototype_object_next */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_string_iterator_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< + * list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_OBJECT_NEXT: + { + return ecma_builtin_string_iterator_prototype_object_next (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_string_iterator_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h new file mode 100644 index 00000000..adc799d1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %StringIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_STRING_ITERATOR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ECMA_BUILTIN_STRING_ITERATOR_PROTOTYPE_OBJECT_NEXT, 0, 0) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp new file mode 100644 index 00000000..f60cd005 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.cpp @@ -0,0 +1,1560 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-regexp.inc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" +#include "lit-strings.h" + +#if JERRY_BUILTIN_REGEXP +#include "ecma-regexp-object.h" +#endif /* JERRY_BUILTIN_REGEXP */ + +#if JERRY_BUILTIN_STRING + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_STRING_PROTOTYPE_ROUTINE_START = 0, + /* Note: These 4 routines MUST be in this order */ + ECMA_STRING_PROTOTYPE_TO_STRING, + ECMA_STRING_PROTOTYPE_VALUE_OF, + ECMA_STRING_PROTOTYPE_CHAR_AT, + ECMA_STRING_PROTOTYPE_CHAR_CODE_AT, + + ECMA_STRING_PROTOTYPE_CONCAT, + ECMA_STRING_PROTOTYPE_SLICE, + ECMA_STRING_PROTOTYPE_AT, + + ECMA_STRING_PROTOTYPE_LOCALE_COMPARE, + + ECMA_STRING_PROTOTYPE_MATCH, + ECMA_STRING_PROTOTYPE_REPLACE, + ECMA_STRING_PROTOTYPE_SEARCH, + + ECMA_STRING_PROTOTYPE_SPLIT, + ECMA_STRING_PROTOTYPE_SUBSTRING, + ECMA_STRING_PROTOTYPE_TO_LOWER_CASE, + ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE, + ECMA_STRING_PROTOTYPE_TO_UPPER_CASE, + ECMA_STRING_PROTOTYPE_TO_LOCAL_UPPER_CASE, + ECMA_STRING_PROTOTYPE_TRIM, + + ECMA_STRING_PROTOTYPE_SUBSTR, + + ECMA_STRING_PROTOTYPE_REPEAT, + ECMA_STRING_PROTOTYPE_CODE_POINT_AT, + ECMA_STRING_PROTOTYPE_PAD_START, + ECMA_STRING_PROTOTYPE_PAD_END, + /* Note: These 5 routines MUST be in this order */ + ECMA_STRING_PROTOTYPE_LAST_INDEX_OF, + ECMA_STRING_PROTOTYPE_INDEX_OF, + ECMA_STRING_PROTOTYPE_STARTS_WITH, + ECMA_STRING_PROTOTYPE_INCLUDES, + ECMA_STRING_PROTOTYPE_ENDS_WITH, + + ECMA_STRING_PROTOTYPE_ITERATOR, + ECMA_STRING_PROTOTYPE_REPLACE_ALL, + ECMA_STRING_PROTOTYPE_MATCH_ALL, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-string-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID string_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup stringprototype ECMA String.prototype object built-in + * @{ + */ + +/** + * The String.prototype object's 'toString' and 'valueOf' routines + * + * See also: + * ECMA-262 v5, 15.5.4.2 + * ECMA-262 v5, 15.5.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_string (this_arg)) + { + return ecma_copy_value (this_arg); + } + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_STRING)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (ecma_is_value_string (ext_object_p->u.cls.u3.value)); + + return ecma_copy_value (ext_object_p->u.cls.u3.value); + } + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_STRING_OBJECT); +} /* ecma_builtin_string_prototype_object_to_string */ + +/** + * Helper function for the String.prototype object's 'charAt' and charCodeAt' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_char_at_helper (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg, /**< routine's argument */ + bool charcode_mode) /**< routine mode */ +{ + /* 3 */ + ecma_number_t index_num; + ecma_value_t to_num_result = ecma_op_to_integer (arg, &index_num); + + if (JERRY_UNLIKELY (!ecma_is_value_empty (to_num_result))) + { + return to_num_result; + } + + /* 2 */ + ecma_string_t *original_string_p = ecma_op_to_string (this_arg); + if (JERRY_UNLIKELY (original_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 4 */ + const lit_utf8_size_t len = ecma_string_get_length (original_string_p); + + /* 5 */ + // When index_num is NaN, then the first two comparisons are false + if (index_num < 0 || index_num >= len || (ecma_number_is_nan (index_num) && len == 0)) + { + ecma_deref_ecma_string (original_string_p); + return (charcode_mode ? ecma_make_nan_value () : ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY)); + } + + /* 6 */ + /* + * String length is currently uint32_t, but index_num may be bigger, + * ToInteger performs floor, while ToUInt32 performs modulo 2^32, + * hence after the check 0 <= index_num < len we assume to_uint32 can be used. + * We assume to_uint32 (NaN) is 0. + */ + JERRY_ASSERT (ecma_number_is_nan (index_num) || ecma_number_to_uint32 (index_num) == ecma_number_trunc (index_num)); + + ecma_char_t new_ecma_char = ecma_string_get_char_at_pos (original_string_p, ecma_number_to_uint32 (index_num)); + ecma_deref_ecma_string (original_string_p); + + return (charcode_mode ? ecma_make_uint32_value (new_ecma_char) + : ecma_make_string_value (ecma_new_ecma_string_from_code_unit (new_ecma_char))); +} /* ecma_builtin_string_prototype_char_at_helper */ + +/** + * The String.prototype object's 'concat' routine + * + * See also: + * ECMA-262 v5, 15.5.4.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_concat (ecma_string_t *this_string_p, /**< this argument */ + const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number) /**< number of arguments */ +{ + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (this_string_p); + + /* 5 */ + for (uint32_t arg_index = 0; arg_index < arguments_number; ++arg_index) + { + /* 5a, b */ + ecma_string_t *get_arg_string_p = ecma_op_to_string (argument_list_p[arg_index]); + + if (JERRY_UNLIKELY (get_arg_string_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + return ECMA_VALUE_ERROR; + } + + ecma_stringbuilder_append (&builder, get_arg_string_p); + + ecma_deref_ecma_string (get_arg_string_p); + } + + /* 6 */ + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_string_prototype_object_concat */ + +/** + * The String.prototype object's 'localeCompare' routine + * + * See also: + * ECMA-262 v5, 15.5.4.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_locale_compare (ecma_string_t *this_string_p, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + /* 3. */ + ecma_string_t *arg_string_p = ecma_op_to_string (arg); + + if (JERRY_UNLIKELY (arg_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + + if (ecma_compare_ecma_strings_relational (this_string_p, arg_string_p)) + { + result = ECMA_NUMBER_MINUS_ONE; + } + else if (!ecma_compare_ecma_strings (this_string_p, arg_string_p)) + { + result = ECMA_NUMBER_ONE; + } + else + { + result = ECMA_NUMBER_ZERO; + } + + ecma_deref_ecma_string (arg_string_p); + + return ecma_make_number_value (result); +} /* ecma_builtin_string_prototype_object_locale_compare */ + +#if JERRY_BUILTIN_REGEXP +/** + * The String.prototype object's 'match' routine + * + * See also: + * ECMA-262 v5, 15.5.4.10 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_match (ecma_value_t this_argument, /**< this argument */ + ecma_value_t regexp_arg) /**< routine's argument */ +{ + /* 3. */ + if (!(ecma_is_value_undefined (regexp_arg) || ecma_is_value_null (regexp_arg))) + { + /* 3.a */ + ecma_value_t matcher = ecma_op_get_method_by_symbol_id (regexp_arg, LIT_GLOBAL_SYMBOL_MATCH); + + /* 3.b */ + if (ECMA_IS_VALUE_ERROR (matcher)) + { + return matcher; + } + + /* 3.c */ + if (!ecma_is_value_undefined (matcher)) + { + /* 3.c.i */ + ecma_object_t *matcher_method = ecma_get_object_from_value (matcher); + ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_argument, 1); + ecma_deref_object (matcher_method); + return result; + } + } + + /* 4. */ + ecma_string_t *this_str_p = ecma_op_to_string (this_argument); + + /* 5. */ + if (JERRY_UNLIKELY (this_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (regexp_obj_p == NULL)) + { + ecma_deref_ecma_string (this_str_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t new_regexp = ecma_op_create_regexp_from_pattern (regexp_obj_p, regexp_arg, ECMA_VALUE_UNDEFINED); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (new_regexp)) + { + ecma_deref_object (regexp_obj_p); + ecma_deref_ecma_string (this_str_p); + return new_regexp; + } + ecma_value_t this_str_value = ecma_make_string_value (this_str_p); + + /* 8. */ + ecma_value_t ret_value = ecma_op_invoke_by_symbol_id (new_regexp, LIT_GLOBAL_SYMBOL_MATCH, &this_str_value, 1); + + ecma_deref_ecma_string (this_str_p); + ecma_free_value (new_regexp); + + return ret_value; +} /* ecma_builtin_string_prototype_object_match */ + +/** + * The String.prototype object's 'matchAll' routine + * + * See also: + * ECMA-262 v11, 21.1.3.12 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_match_all (ecma_value_t this_argument, /**< this argument */ + ecma_value_t regexp_arg) /**< routine's argument */ +{ + /* 2. */ + if (!ecma_is_value_null (regexp_arg) && !ecma_is_value_undefined (regexp_arg)) + { + /* 2.a */ + ecma_value_t is_regexp = ecma_op_is_regexp (regexp_arg); + + if (ECMA_IS_VALUE_ERROR (is_regexp)) + { + return is_regexp; + } + + /* 2.b */ + if (ecma_is_value_true (is_regexp)) + { + /* 2.b.i */ + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp_arg); + ecma_value_t get_flags = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (get_flags)) + { + return get_flags; + } + + /* 2.b.ii */ + if (!ecma_op_require_object_coercible (get_flags)) + { + ecma_free_value (get_flags); + return ECMA_VALUE_ERROR; + } + + /* 2.b.iii */ + ecma_string_t *flags = ecma_op_to_string (get_flags); + + ecma_free_value (get_flags); + + if (JERRY_UNLIKELY (flags == NULL)) + { + return ECMA_VALUE_ERROR; + } + + uint16_t parsed_flag; + ecma_value_t flag_parse = ecma_regexp_parse_flags (flags, &parsed_flag); + + ecma_deref_ecma_string (flags); + + if (ECMA_IS_VALUE_ERROR (flag_parse)) + { + return flag_parse; + } + + if (!(parsed_flag & RE_FLAG_GLOBAL)) + { + return ecma_raise_type_error (ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG); + } + } + + /* 2.c */ + ecma_value_t matcher = ecma_op_get_method_by_symbol_id (regexp_arg, LIT_GLOBAL_SYMBOL_MATCH_ALL); + + if (ECMA_IS_VALUE_ERROR (matcher)) + { + return matcher; + } + + /* 2.d */ + if (!ecma_is_value_undefined (matcher)) + { + /* 2.d.i */ + ecma_object_t *matcher_method = ecma_get_object_from_value (matcher); + ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_argument, 1); + ecma_deref_object (matcher_method); + return result; + } + } + + /* 3. */ + ecma_string_t *str_p = ecma_op_to_string (this_argument); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 4. */ + ecma_object_t *new_regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (new_regexp_obj_p == NULL)) + { + ecma_deref_ecma_string (str_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t new_regexp = ecma_op_create_regexp_from_pattern (new_regexp_obj_p, regexp_arg, ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (new_regexp)) + { + ecma_deref_ecma_string (str_p); + ecma_deref_object (new_regexp_obj_p); + return new_regexp; + } + + /* 5. */ + ecma_value_t string_arg = ecma_make_string_value (str_p); + ecma_value_t ret_value = ecma_op_invoke_by_symbol_id (new_regexp, LIT_GLOBAL_SYMBOL_MATCH_ALL, &string_arg, 1); + + ecma_deref_ecma_string (str_p); + ecma_free_value (new_regexp); + + return ret_value; +} /* ecma_builtin_string_prototype_object_match_all */ + +/** + * The String.prototype object's 'replace' and 'replaceAll' routine + * + * See also: + * ECMA-262 v5, 15.5.4.11 (replace ES5) + * ECMA-262 v6, 21.1.3.14 (replace ES6) + * ECMA-262 v12, 21.1.3.18 (replaceAll) + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_replace_helper (ecma_value_t this_value, /**< this argument */ + ecma_value_t search_value, /**< routine's first argument */ + ecma_value_t replace_value, /**< routine's second argument */ + bool replace_all) +{ + ecma_string_t *result_string_p; + lit_utf8_byte_t *search_buf_p; + uint8_t search_flags; + uint8_t input_flags; + + if (!(ecma_is_value_undefined (search_value) || ecma_is_value_null (search_value))) + { + if (replace_all) + { + ecma_value_t is_regexp = ecma_op_is_regexp (search_value); + + if (ECMA_IS_VALUE_ERROR (is_regexp)) + { + return is_regexp; + } + + if (ecma_is_value_true (is_regexp)) + { + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (search_value); + ecma_value_t get_flags = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + + if (ECMA_IS_VALUE_ERROR (get_flags)) + { + return get_flags; + } + + if (!ecma_op_require_object_coercible (get_flags)) + { + ecma_free_value (get_flags); + return ECMA_VALUE_ERROR; + } + + ecma_string_t *flags = ecma_op_to_string (get_flags); + + ecma_free_value (get_flags); + + if (JERRY_UNLIKELY (flags == NULL)) + { + return ECMA_VALUE_ERROR; + } + + bool have_global_flag = lit_find_char_in_string (flags, LIT_CHAR_LOWERCASE_G); + + ecma_deref_ecma_string (flags); + + if (!have_global_flag) + { + return ecma_raise_type_error (ECMA_ERR_REGEXP_ARGUMENT_SHOULD_HAVE_GLOBAL_FLAG); + } + } + } + + ecma_object_t *obj_p = ecma_get_object_from_value (ecma_op_to_object (search_value)); + ecma_value_t replace_symbol = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_REPLACE); + ecma_deref_object (obj_p); + + if (ECMA_IS_VALUE_ERROR (replace_symbol)) + { + return replace_symbol; + } + + if (!ecma_is_value_undefined (replace_symbol) && !ecma_is_value_null (replace_symbol)) + { + ecma_value_t arguments[] = { this_value, replace_value }; + ecma_value_t replace_result = ecma_op_function_validated_call (replace_symbol, search_value, arguments, 2); + ecma_free_value (replace_symbol); + + return replace_result; + } + } + + ecma_string_t *input_str_p = ecma_op_to_string (this_value); + + if (input_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ECMA_VALUE_ERROR; + + ecma_string_t *search_str_p = ecma_op_to_string (search_value); + if (search_str_p == NULL) + { + ecma_deref_ecma_string (input_str_p); + return result; + } + + ecma_replace_context_t replace_ctx; + replace_ctx.capture_count = 0; + replace_ctx.u.captures_p = NULL; + + replace_ctx.replace_str_p = NULL; + if (!ecma_op_is_callable (replace_value)) + { + replace_ctx.replace_str_p = ecma_op_to_string (replace_value); + if (replace_ctx.replace_str_p == NULL) + { + goto cleanup_search; + } + } + + input_flags = ECMA_STRING_FLAG_IS_ASCII; + replace_ctx.string_p = ecma_string_get_chars (input_str_p, &(replace_ctx.string_size), NULL, NULL, &input_flags); + + lit_utf8_size_t search_size; + lit_utf8_size_t search_length; + search_flags = ECMA_STRING_FLAG_IS_ASCII; + search_buf_p = (lit_utf8_byte_t *) ecma_string_get_chars (search_str_p, &search_size, &search_length, NULL, &search_flags); + + result_string_p = NULL; + + if (replace_ctx.string_size >= search_size) + { + replace_ctx.builder = ecma_stringbuilder_create (); + replace_ctx.matched_size = search_size; + const lit_utf8_byte_t *const input_end_p = replace_ctx.string_p + replace_ctx.string_size; + const lit_utf8_byte_t *const loop_end_p = input_end_p - search_size; + const lit_utf8_byte_t *last_match_end_p = replace_ctx.string_p; + const lit_utf8_byte_t *curr_p = replace_ctx.string_p; + + lit_utf8_size_t pos = 0; + while (curr_p <= loop_end_p) + { + if (!memcmp (curr_p, search_buf_p, search_size)) + { + const lit_utf8_size_t prefix_size = (lit_utf8_size_t) (curr_p - last_match_end_p); + ecma_stringbuilder_append_raw (&replace_ctx.builder, last_match_end_p, prefix_size); + + last_match_end_p = curr_p + search_size; + + if (replace_ctx.replace_str_p == NULL) + { + ecma_object_t *function_p = ecma_get_object_from_value (replace_value); + + ecma_value_t args[] = { ecma_make_string_value (search_str_p), + ecma_make_uint32_value (pos), + ecma_make_string_value (input_str_p) }; + + result = ecma_op_function_call (function_p, ECMA_VALUE_UNDEFINED, args, 3); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_stringbuilder_destroy (&replace_ctx.builder); + goto cleanup_replace; + } + + ecma_string_t *const result_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (result_str_p == NULL) + { + ecma_stringbuilder_destroy (&replace_ctx.builder); + result = ECMA_VALUE_ERROR; + goto cleanup_replace; + } + + ecma_stringbuilder_append (&replace_ctx.builder, result_str_p); + ecma_deref_ecma_string (result_str_p); + } + else + { + replace_ctx.matched_p = curr_p; + replace_ctx.match_byte_pos = (lit_utf8_size_t) (curr_p - replace_ctx.string_p); + + ecma_builtin_replace_substitute (&replace_ctx); + } + + if (!replace_all || last_match_end_p == input_end_p) + { + break; + } + + if (search_size != 0) + { + curr_p = last_match_end_p; + pos += search_length; + continue; + } + } + + pos++; + lit_utf8_incr (&curr_p); + } + + ecma_stringbuilder_append_raw (&replace_ctx.builder, + last_match_end_p, + (lit_utf8_size_t) (input_end_p - last_match_end_p)); + result_string_p = ecma_stringbuilder_finalize (&replace_ctx.builder); + } + + if (result_string_p == NULL) + { + ecma_ref_ecma_string (input_str_p); + result_string_p = input_str_p; + } + + result = ecma_make_string_value (result_string_p); + +cleanup_replace: + if (input_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) replace_ctx.string_p, replace_ctx.string_size); + } + + if (search_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) search_buf_p, search_size); + } + + if (replace_ctx.replace_str_p != NULL) + { + ecma_deref_ecma_string (replace_ctx.replace_str_p); + } + +cleanup_search: + ecma_deref_ecma_string (search_str_p); + ecma_deref_ecma_string (input_str_p); + + return result; +} /* ecma_builtin_string_prototype_object_replace_helper */ + +/** + * The String.prototype object's 'search' routine + * + * See also: + * ECMA-262 v5, 15.5.4.12 + * ECMA-262 v6, 21.1.3.15 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_search (ecma_value_t this_value, /**< this argument */ + ecma_value_t regexp_value) /**< routine's argument */ +{ + if (!(ecma_is_value_undefined (regexp_value) || ecma_is_value_null (regexp_value))) + { + ecma_object_t *obj_p = ecma_get_object_from_value (ecma_op_to_object (regexp_value)); + ecma_value_t search_symbol = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_SEARCH); + ecma_deref_object (obj_p); + + if (ECMA_IS_VALUE_ERROR (search_symbol)) + { + return search_symbol; + } + + if (!ecma_is_value_undefined (search_symbol) && !ecma_is_value_null (search_symbol)) + { + ecma_value_t search_result = ecma_op_function_validated_call (search_symbol, regexp_value, &this_value, 1); + ecma_free_value (search_symbol); + return search_result; + } + } + + ecma_value_t result = ECMA_VALUE_ERROR; + + ecma_string_t *string_p = ecma_op_to_string (this_value); + if (string_p == NULL) + { + return result; + } + + ecma_string_t *pattern_p = ecma_regexp_read_pattern_str_helper (regexp_value); + if (pattern_p == NULL) + { + ecma_deref_ecma_string (string_p); + return result; + } + + ecma_object_t *new_regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (new_regexp_obj_p == NULL)) + { + ecma_deref_ecma_string (string_p); + ecma_deref_ecma_string (pattern_p); + return result; + } + + ecma_value_t new_regexp = + ecma_op_create_regexp_from_pattern (new_regexp_obj_p, ecma_make_string_value (pattern_p), ECMA_VALUE_UNDEFINED); + + ecma_deref_ecma_string (pattern_p); + + if (ECMA_IS_VALUE_ERROR (new_regexp)) + { + ecma_deref_ecma_string (string_p); + ecma_deref_object (new_regexp_obj_p); + return result; + } + + ecma_object_t *regexp_obj_p = ecma_get_object_from_value (new_regexp); + ecma_value_t this_str_value = ecma_make_string_value (string_p); + result = ecma_op_invoke_by_symbol_id (new_regexp, LIT_GLOBAL_SYMBOL_SEARCH, &this_str_value, 1); + ecma_deref_object (regexp_obj_p); + ecma_deref_ecma_string (string_p); + + return result; +} /* ecma_builtin_string_prototype_object_search */ + +#endif /* JERRY_BUILTIN_REGEXP */ + +/** + * The String.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v5, 15.5.4.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_slice (ecma_string_t *get_string_val, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + const lit_utf8_size_t len = ecma_string_get_length (get_string_val); + + /* 4. 6. */ + lit_utf8_size_t start = 0, end = len; + + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (arg1, len, &start))) + { + return ECMA_VALUE_ERROR; + } + + /* 5. 7. */ + if (ecma_is_value_undefined (arg2)) + { + end = len; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (arg2, len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + + JERRY_ASSERT (start <= len && end <= len); + + /* 8-9. */ + ecma_string_t *new_str_p = ecma_string_substr (get_string_val, start, end); + + return ecma_make_string_value (new_str_p); +} /* ecma_builtin_string_prototype_object_slice */ + +/** + * The String.prototype object's 'at' routine + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal + * from: https://tc39.es/proposal-relative-indexing-method + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_at (ecma_string_t *string_val, /**< this argument */ + const ecma_value_t index) /**< index argument */ +{ + ecma_length_t len = (ecma_length_t) ecma_string_get_length (string_val); + ecma_length_t res_index; + ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index); + + if (return_value != ECMA_VALUE_EMPTY) + { + return return_value; + } + + ecma_char_t character = ecma_string_get_char_at_pos (string_val, (lit_utf8_size_t) res_index); + + return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (character)); +} /* ecma_builtin_string_prototype_object_at */ + +/** + * The String.prototype object's 'split' routine + * + * See also: + * ECMA-262 v5, 15.5.4.14 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_split (ecma_value_t this_value, /**< this argument */ + ecma_value_t separator_value, /**< separator */ + ecma_value_t limit_value) /**< limit */ +{ + if (!(ecma_is_value_undefined (separator_value) || ecma_is_value_null (separator_value))) + { + ecma_object_t *obj_p = ecma_get_object_from_value (ecma_op_to_object (separator_value)); + ecma_value_t split_symbol = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_SPLIT); + ecma_deref_object (obj_p); + + if (ECMA_IS_VALUE_ERROR (split_symbol)) + { + return split_symbol; + } + + if (!ecma_is_value_undefined (split_symbol) && !ecma_is_value_null (split_symbol)) + { + ecma_value_t arguments[] = { this_value, limit_value }; + ecma_value_t split_result = ecma_op_function_validated_call (split_symbol, separator_value, arguments, 2); + ecma_free_value (split_symbol); + + return split_result; + } + } + + ecma_value_t result = ECMA_VALUE_ERROR; + ecma_string_t *end_substr_p; + ecma_value_t put_result; + + lit_utf8_size_t string_size; + uint8_t string_flags; + lit_utf8_byte_t *string_buffer_p; + lit_utf8_size_t separator_size; + uint8_t separator_flags; + lit_utf8_byte_t *separator_buffer_p; + + lit_utf8_byte_t *string_end_p; + lit_utf8_byte_t *compare_end_p; + const lit_utf8_byte_t *current_p; + const lit_utf8_byte_t *last_str_begin_p; + + lit_utf8_size_t array_length; + + uint32_t limit; + + ecma_string_t *separator_p; + ecma_object_t *array_p; + + /* 4. */ + ecma_string_t *string_p = ecma_op_to_string (this_value); + if (string_p == NULL) + { + return result; + } + + /* 8. */ + limit = UINT32_MAX - 1; + + if (!ecma_is_value_undefined (limit_value)) + { + /* ECMA-262 v11, 21.1.3.20 6 */ + ecma_number_t num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (limit_value, &num))) + { + goto cleanup_string; + } + limit = ecma_number_to_uint32 (num); + } + + /* 12. */ + separator_p = ecma_op_to_string (separator_value); + if (separator_p == NULL) + { + goto cleanup_string; + } + + /* 6. */ + array_p = ecma_op_new_array_object (0); + result = ecma_make_object_value (array_p); + + /* 14. */ + if (limit == 0) + { + goto cleanup_separator; + } + + /* 6. */ + array_length = 0; + + /* 15. */ + if (ecma_is_value_undefined (separator_value)) + { + ecma_value_t put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + goto cleanup_separator; + } + + /* 16. */ + if (ecma_string_is_empty (string_p)) + { + if (!ecma_string_is_empty (separator_p)) + { + ecma_value_t put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + } + + goto cleanup_separator; + } + + string_flags = ECMA_STRING_FLAG_IS_ASCII; + string_buffer_p = (lit_utf8_byte_t *) ecma_string_get_chars (string_p, &string_size, NULL, NULL, &string_flags); + separator_flags = ECMA_STRING_FLAG_IS_ASCII; + separator_buffer_p = (lit_utf8_byte_t *) ecma_string_get_chars (separator_p, &separator_size, NULL, NULL, &separator_flags); + + string_end_p = string_buffer_p + string_size; + compare_end_p = JERRY_MIN (string_end_p - separator_size + 1, string_end_p); + current_p = string_buffer_p; + last_str_begin_p = string_buffer_p; + + while (current_p < compare_end_p) + { + if (!memcmp (current_p, separator_buffer_p, separator_size) && (last_str_begin_p != current_p + separator_size)) + { + ecma_string_t *substr_p = + ecma_new_ecma_string_from_utf8 (last_str_begin_p, (lit_utf8_size_t) (current_p - last_str_begin_p)); + ecma_value_t put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + ecma_make_string_value (substr_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + ecma_deref_ecma_string (substr_p); + + if (array_length >= limit) + { + goto cleanup_buffers; + } + + current_p += separator_size; + last_str_begin_p = current_p; + continue; + } + + lit_utf8_incr (¤t_p); + } + + end_substr_p = ecma_new_ecma_string_from_utf8 (last_str_begin_p, (lit_utf8_size_t) (string_end_p - last_str_begin_p)); + put_result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (end_substr_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (put_result == ECMA_VALUE_TRUE); + ecma_deref_ecma_string (end_substr_p); + +cleanup_buffers: + if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) string_buffer_p, string_size); + } + + if (separator_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) separator_buffer_p, separator_size); + } + +cleanup_separator: + ecma_deref_ecma_string (separator_p); +cleanup_string: + ecma_deref_ecma_string (string_p); + return result; +} /* ecma_builtin_string_prototype_object_split */ + +/** + * The String.prototype object's 'substring' routine + * + * See also: + * ECMA-262 v5, 15.5.4.15 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_substring (ecma_string_t *original_string_p, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + /* 3 */ + const lit_utf8_size_t len = ecma_string_get_length (original_string_p); + lit_utf8_size_t start = 0, end = len; + + /* 4 */ + ecma_number_t start_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg1, &start_num))) + { + return ECMA_VALUE_ERROR; + } + + /* 6 */ + start = (uint32_t) JERRY_MIN (JERRY_MAX (start_num, 0), len); + + /* 5 */ + if (ecma_is_value_undefined (arg2)) + { + end = len; + } + else + { + /* 5 part 2 */ + ecma_number_t end_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg2, &end_num))) + { + return ECMA_VALUE_ERROR; + } + /* 7 */ + end = (uint32_t) JERRY_MIN (JERRY_MAX (end_num, 0), len); + } + + JERRY_ASSERT (start <= len && end <= len); + + /* 8 */ + uint32_t from = start < end ? start : end; + + /* 9 */ + uint32_t to = start > end ? start : end; + + /* 10 */ + ecma_string_t *new_str_p = ecma_string_substr (original_string_p, from, to); + return ecma_make_string_value (new_str_p); +} /* ecma_builtin_string_prototype_object_substring */ + +/** + * The common implementation of the String.prototype object's + * 'toLowerCase', 'toLocaleLowerCase', 'toUpperCase', 'toLocalUpperCase' routines + * + * See also: + * ECMA-262 v5, 15.5.4.16 + * ECMA-262 v5, 15.5.4.17 + * ECMA-262 v5, 15.5.4.18 + * ECMA-262 v5, 15.5.4.19 + * + * Helper function to convert a string to upper or lower case. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_conversion_helper (ecma_string_t *input_string_p, /**< this argument */ + bool lower_case) /**< convert to lower (true) + * or upper (false) case */ +{ + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + ECMA_STRING_TO_UTF8_STRING (input_string_p, input_start_p, input_start_size); + + const lit_utf8_byte_t *input_curr_p = input_start_p; + const lit_utf8_byte_t *input_str_end_p = input_start_p + input_start_size; + + while (input_curr_p < input_str_end_p) + { + lit_code_point_t cp = lit_cesu8_read_next (&input_curr_p); + + if (lit_is_code_point_utf16_high_surrogate (cp) && input_curr_p < input_str_end_p) + { + const ecma_char_t next_ch = lit_cesu8_peek_next (input_curr_p); + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + cp = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) cp, next_ch); + input_curr_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + if (lower_case) + { + lit_char_to_lower_case (cp, &builder); + } + else + { + lit_char_to_upper_case (cp, &builder); + } + } + + ECMA_FINALIZE_UTF8_STRING (input_start_p, input_start_size); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_string_prototype_object_conversion_helper */ + +/** + * The String.prototype object's 'trim' routine + * + * See also: + * ECMA-262 v5, 15.5.4.20 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_trim (ecma_string_t *original_string_p) /**< this argument */ +{ + ecma_string_t *trimmed_string_p = ecma_string_trim (original_string_p); + + return ecma_make_string_value (trimmed_string_p); +} /* ecma_builtin_string_prototype_object_trim */ + +/** + * The String.prototype object's 'repeat' routine + * + * See also: + * ECMA-262 v6, 21.1.3.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_repeat (ecma_string_t *original_string_p, /**< this argument */ + ecma_value_t repeat) /**< times to repeat */ +{ + ecma_string_t *ret_string_p; + + /* 4 */ + ecma_number_t count_number; + ecma_value_t count_value = ecma_op_to_integer (repeat, &count_number); + + /* 5 */ + if (ECMA_IS_VALUE_ERROR (count_value)) + { + return count_value; + } + + int32_t repeat_count = ecma_number_to_int32 (count_number); + + bool isNan = ecma_number_is_nan (count_number); + + /* 6, 7 */ + if (count_number < 0 || (!isNan && ecma_number_is_infinity (count_number))) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_COUNT_VALUE); + } + + lit_utf8_size_t size = ecma_string_get_size (original_string_p); + + if (repeat_count == 0 || size == 0 || isNan) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + if ((uint32_t) repeat_count >= (ECMA_STRING_SIZE_LIMIT / size)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_STRING_); + } + + lit_utf8_size_t total_size = size * (lit_utf8_size_t) repeat_count; + + JMEM_DEFINE_LOCAL_ARRAY (str_buffer, total_size, lit_utf8_byte_t); + + ecma_string_to_cesu8_bytes (original_string_p, str_buffer, size); + lit_utf8_byte_t *buffer_ptr = str_buffer + size; + + for (int32_t n = 1; n < repeat_count; n++) + { + memcpy (buffer_ptr, str_buffer, size); + buffer_ptr += size; + } + + ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); + JMEM_FINALIZE_LOCAL_ARRAY (str_buffer); + + return ecma_make_string_value (ret_string_p); +} /* ecma_builtin_string_prototype_object_repeat */ + +/** + * The String.prototype object's 'codePointAt' routine + * + * See also: + * ECMA-262 v6, 21.1.3.3 + * + * @return lit_code_point_t + */ +static ecma_value_t +ecma_builtin_string_prototype_object_code_point_at (ecma_string_t *this_string_p, /**< this argument */ + ecma_value_t pos) /**< given position */ +{ + ecma_number_t pos_num; + ecma_value_t error = ecma_op_to_integer (pos, &pos_num); + + if (ECMA_IS_VALUE_ERROR (error)) + { + return error; + } + + lit_utf8_size_t length = ecma_string_get_length (this_string_p); + + if (pos_num < 0 || pos_num >= length) + { + return ECMA_VALUE_UNDEFINED; + } + + uint32_t index = (uint32_t) pos_num; + + ecma_char_t first = ecma_string_get_char_at_pos (this_string_p, index); + + if (first < LIT_UTF16_HIGH_SURROGATE_MIN || first > LIT_UTF16_HIGH_SURROGATE_MAX || index + 1 == length) + { + return ecma_make_uint32_value (first); + } + + ecma_char_t second = ecma_string_get_char_at_pos (this_string_p, index + 1); + + if (second < LIT_UTF16_LOW_SURROGATE_MARKER || second > LIT_UTF16_LOW_SURROGATE_MAX) + { + return ecma_make_uint32_value (first); + } + + return ecma_make_uint32_value (lit_convert_surrogate_pair_to_code_point (first, second)); +} /* ecma_builtin_string_prototype_object_code_point_at */ + +#if JERRY_BUILTIN_ANNEXB + +/** + * The String.prototype object's 'substr' routine + * + * See also: + * ECMA-262 v5, B.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_substr (ecma_string_t *this_string_p, /**< this argument */ + ecma_value_t start, /**< routine's first argument */ + ecma_value_t length) /**< routine's second argument */ +{ + /* 2. */ + ecma_number_t start_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (start, &start_num))) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_number_t length_num = ecma_number_make_infinity (false); + + if (!ecma_is_value_undefined (length)) + { + ecma_number_t len; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (length, &len))) + { + return ECMA_VALUE_ERROR; + } + + length_num = ecma_number_is_nan (len) ? 0 : len; + } + + /* 4. */ + lit_utf8_size_t this_len = ecma_string_get_length (this_string_p); + + /* 5. */ + uint32_t from = (uint32_t) ((start_num < 0) ? JERRY_MAX (this_len + start_num, 0) : start_num); + + if (from > this_len) + { + from = this_len; + } + + /* 6. */ + ecma_number_t to_num = JERRY_MIN (JERRY_MAX (length_num, 0), this_len - from); + + /* 7. */ + uint32_t to = from + (uint32_t) to_num; + + /* 8. */ + ecma_string_t *new_str_p = ecma_string_substr (this_string_p, from, to); + return ecma_make_string_value (new_str_p); +} /* ecma_builtin_string_prototype_object_substr */ + +#endif /* JERRY_BUILTIN_ANNEXB */ + +/** + * The String.prototype object's @@iterator routine + * + * See also: + * ECMA-262 v6, 21.1.3.27 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_iterator (ecma_value_t to_string) /**< this argument */ +{ + return ecma_op_create_iterator_object (ecma_copy_value (to_string), + ecma_builtin_get (ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE), + ECMA_OBJECT_CLASS_STRING_ITERATOR, + ECMA_ITERATOR_VALUES); +} /* ecma_builtin_string_prototype_object_iterator */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_string_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (builtin_routine_id <= ECMA_STRING_PROTOTYPE_VALUE_OF) + { + return ecma_builtin_string_prototype_object_to_string (this_arg); + } + + if (!ecma_op_require_object_coercible (this_arg)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t arg1 = arguments_list_p[0]; + ecma_value_t arg2 = arguments_list_p[1]; + +#if JERRY_BUILTIN_REGEXP + if (builtin_routine_id == ECMA_STRING_PROTOTYPE_MATCH) + { + return ecma_builtin_string_prototype_object_match (this_arg, arg1); + } + + if (builtin_routine_id == ECMA_STRING_PROTOTYPE_MATCH_ALL) + { + return ecma_builtin_string_prototype_object_match_all (this_arg, arg1); + } +#endif /* JERRY_BUILTIN_REGEXP */ + + if (builtin_routine_id <= ECMA_STRING_PROTOTYPE_CHAR_CODE_AT) + { + return ecma_builtin_string_prototype_char_at_helper (this_arg, + arg1, + builtin_routine_id == ECMA_STRING_PROTOTYPE_CHAR_CODE_AT); + } + +#if JERRY_BUILTIN_REGEXP + if (builtin_routine_id == ECMA_STRING_PROTOTYPE_REPLACE) + { + return ecma_builtin_string_prototype_object_replace_helper (this_arg, arg1, arg2, false); + } + + else if (builtin_routine_id == ECMA_STRING_PROTOTYPE_REPLACE_ALL) + { + return ecma_builtin_string_prototype_object_replace_helper (this_arg, arg1, arg2, true); + } +#endif /* JERRY_BUILTIN_REGEXP */ + + ecma_string_t *string_p = ecma_op_to_string (this_arg); + + if (JERRY_UNLIKELY (string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t to_string_val = ecma_make_string_value (string_p); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + switch (builtin_routine_id) + { + case ECMA_STRING_PROTOTYPE_CONCAT: + { + ret_value = ecma_builtin_string_prototype_object_concat (string_p, arguments_list_p, arguments_number); + break; + } + case ECMA_STRING_PROTOTYPE_SLICE: + { + ret_value = ecma_builtin_string_prototype_object_slice (string_p, arg1, arg2); + break; + } + case ECMA_STRING_PROTOTYPE_AT: + { + ret_value = ecma_builtin_string_prototype_object_at (string_p, arg1); + break; + } + case ECMA_STRING_PROTOTYPE_LAST_INDEX_OF: + case ECMA_STRING_PROTOTYPE_INDEX_OF: + case ECMA_STRING_PROTOTYPE_STARTS_WITH: + case ECMA_STRING_PROTOTYPE_INCLUDES: + case ECMA_STRING_PROTOTYPE_ENDS_WITH: + { + ecma_string_index_of_mode_t mode; + mode = (ecma_string_index_of_mode_t) (builtin_routine_id - ECMA_STRING_PROTOTYPE_LAST_INDEX_OF); + ret_value = ecma_builtin_helper_string_prototype_object_index_of (string_p, arg1, arg2, mode); + break; + } + case ECMA_STRING_PROTOTYPE_LOCALE_COMPARE: + { + ret_value = ecma_builtin_string_prototype_object_locale_compare (string_p, arg1); + break; + } +#if JERRY_BUILTIN_REGEXP + case ECMA_STRING_PROTOTYPE_SEARCH: + { + ret_value = ecma_builtin_string_prototype_object_search (to_string_val, arg1); + break; + } +#endif /* JERRY_BUILTIN_REGEXP */ + case ECMA_STRING_PROTOTYPE_SPLIT: + { + ret_value = ecma_builtin_string_prototype_object_split (to_string_val, arg1, arg2); + break; + } + case ECMA_STRING_PROTOTYPE_SUBSTRING: + { + ret_value = ecma_builtin_string_prototype_object_substring (string_p, arg1, arg2); + break; + } + case ECMA_STRING_PROTOTYPE_TO_LOWER_CASE: + case ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE: + case ECMA_STRING_PROTOTYPE_TO_UPPER_CASE: + case ECMA_STRING_PROTOTYPE_TO_LOCAL_UPPER_CASE: + { + bool is_lower_case = builtin_routine_id <= ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE; + ret_value = ecma_builtin_string_prototype_object_conversion_helper (string_p, is_lower_case); + break; + } + case ECMA_STRING_PROTOTYPE_TRIM: + { + ret_value = ecma_builtin_string_prototype_object_trim (string_p); + break; + } +#if JERRY_BUILTIN_ANNEXB + case ECMA_STRING_PROTOTYPE_SUBSTR: + { + ret_value = ecma_builtin_string_prototype_object_substr (string_p, arg1, arg2); + break; + } +#endif /* JERRY_BUILTIN_ANNEXB */ + case ECMA_STRING_PROTOTYPE_REPEAT: + { + ret_value = ecma_builtin_string_prototype_object_repeat (string_p, arg1); + break; + } + case ECMA_STRING_PROTOTYPE_CODE_POINT_AT: + { + ret_value = ecma_builtin_string_prototype_object_code_point_at (string_p, arg1); + break; + } + case ECMA_STRING_PROTOTYPE_ITERATOR: + { + ret_value = ecma_builtin_string_prototype_object_iterator (to_string_val); + break; + } + case ECMA_STRING_PROTOTYPE_PAD_END: + case ECMA_STRING_PROTOTYPE_PAD_START: + { + ret_value = ecma_string_pad (to_string_val, arg1, arg2, builtin_routine_id == ECMA_STRING_PROTOTYPE_PAD_START); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_deref_ecma_string (string_p); + + return ret_value; +} /* ecma_builtin_string_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_STRING */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h new file mode 100644 index 00000000..3e54d262 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h @@ -0,0 +1,85 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * String.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_STRING + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.5.4.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_STRING, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Number properties: + * (property name, number value) */ + +/* ECMA-262 v5, 15.5.4 (String.prototype is itself a String object whose value is an empty String), 15.5.5.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FIXED) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_STRING_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_STRING_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE (LIT_MAGIC_STRING_CONCAT, ECMA_STRING_PROTOTYPE_CONCAT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_STRING_PROTOTYPE_SLICE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_AT, ECMA_STRING_PROTOTYPE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_STRING_PROTOTYPE_INDEX_OF, 2, 1) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_STRING_PROTOTYPE_LAST_INDEX_OF, 2, 1) +ROUTINE (LIT_MAGIC_STRING_CHAR_AT_UL, ECMA_STRING_PROTOTYPE_CHAR_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, ECMA_STRING_PROTOTYPE_CHAR_CODE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOCALE_COMPARE_UL, ECMA_STRING_PROTOTYPE_LOCALE_COMPARE, 1, 1) + +#if JERRY_BUILTIN_REGEXP +ROUTINE (LIT_MAGIC_STRING_MATCH, ECMA_STRING_PROTOTYPE_MATCH, 1, 1) +ROUTINE (LIT_MAGIC_STRING_REPLACE, ECMA_STRING_PROTOTYPE_REPLACE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_REPLACE_ALL, ECMA_STRING_PROTOTYPE_REPLACE_ALL, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SEARCH, ECMA_STRING_PROTOTYPE_SEARCH, 1, 1) +#endif /* JERRY_BUILTIN_REGEXP */ + +ROUTINE (LIT_MAGIC_STRING_SPLIT, ECMA_STRING_PROTOTYPE_SPLIT, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SUBSTRING, ECMA_STRING_PROTOTYPE_SUBSTRING, 2, 2) +ROUTINE (LIT_MAGIC_STRING_TO_LOWER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_LOWER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_LOWER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_LOCAL_LOWER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_UPPER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_UPPER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_UPPER_CASE_UL, ECMA_STRING_PROTOTYPE_TO_LOCAL_UPPER_CASE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM, ECMA_STRING_PROTOTYPE_TRIM, 0, 0) + +#if JERRY_BUILTIN_ANNEXB +ROUTINE (LIT_MAGIC_STRING_SUBSTR, ECMA_STRING_PROTOTYPE_SUBSTR, 2, 2) +#endif /* JERRY_BUILTIN_ANNEXB */ + +ROUTINE (LIT_MAGIC_STRING_REPEAT, ECMA_STRING_PROTOTYPE_REPEAT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_STARTS_WITH, ECMA_STRING_PROTOTYPE_STARTS_WITH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_STRING_PROTOTYPE_INCLUDES, 2, 1) +ROUTINE (LIT_MAGIC_STRING_ENDS_WITH, ECMA_STRING_PROTOTYPE_ENDS_WITH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_CODE_POINT_AT, ECMA_STRING_PROTOTYPE_CODE_POINT_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PAD_START, ECMA_STRING_PROTOTYPE_PAD_START, 2, 1) +ROUTINE (LIT_MAGIC_STRING_PAD_END, ECMA_STRING_PROTOTYPE_PAD_END, 2, 1) +ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ECMA_STRING_PROTOTYPE_ITERATOR, 0, 0) +ROUTINE (LIT_MAGIC_STRING_MATCH_ALL, ECMA_STRING_PROTOTYPE_MATCH_ALL, 1, 1) + +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_START, LIT_MAGIC_STRING_TRIM_START, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_LEFT, LIT_MAGIC_STRING_TRIM_START, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_END, LIT_MAGIC_STRING_TRIM_END, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_RIGHT, LIT_MAGIC_STRING_TRIM_END, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_STRING */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.cpp new file mode 100644 index 00000000..0da8ee1e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.cpp @@ -0,0 +1,430 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" +#include "ecma-symbol-object.h" + +#include "jrt.h" +#include "lit-strings.h" + +#if JERRY_BUILTIN_STRING + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_STRING_ROUTINE_START = 0, + ECMA_BUILTIN_STRING_OBJECT_FROM_CHAR_CODE, + ECMA_BUILTIN_STRING_OBJECT_FROM_CODE_POINT, + ECMA_BUILTIN_STRING_OBJECT_RAW, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-string.inc.h" +#define BUILTIN_UNDERSCORED_ID string +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup string ECMA String object built-in + * @{ + */ + +/** + * The String object's 'fromCharCode' routine + * + * See also: + * ECMA-262 v5, 15.5.3.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_object_from_char_code (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + lit_utf8_size_t utf8_buf_size = args_number * LIT_CESU8_MAX_BYTES_IN_CODE_UNIT; + ecma_string_t *ret_string_p = NULL; + bool isError = false; + + JMEM_DEFINE_LOCAL_ARRAY (utf8_buf_p, utf8_buf_size, lit_utf8_byte_t); + + lit_utf8_size_t utf8_buf_used = 0; + + for (uint32_t arg_index = 0; arg_index < args_number; arg_index++) + { + ecma_number_t arg_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (args[arg_index], &arg_num))) + { + isError = true; + break; + } + + uint32_t uint32_char_code = ecma_number_to_uint32 (arg_num); + ecma_char_t code_unit = (uint16_t) uint32_char_code; + + JERRY_ASSERT (utf8_buf_used <= utf8_buf_size - LIT_UTF8_MAX_BYTES_IN_CODE_UNIT); + utf8_buf_used += lit_code_unit_to_utf8 (code_unit, utf8_buf_p + utf8_buf_used); + JERRY_ASSERT (utf8_buf_used <= utf8_buf_size); + } + + if (!isError) + { + ret_string_p = ecma_new_ecma_string_from_utf8 (utf8_buf_p, utf8_buf_used); + } + + JMEM_FINALIZE_LOCAL_ARRAY (utf8_buf_p); + + return isError ? ECMA_VALUE_ERROR : ecma_make_string_value (ret_string_p); +} /* ecma_builtin_string_object_from_char_code */ + +/** + * The String object's 'raw' routine + * + * See also: + * ECMA-262 v6, 21.1.2.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_object_raw (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + /* 1 - 2. */ + const ecma_value_t *substitutions; + uint32_t number_of_substitutions; + ecma_length_t next_index; + ecma_stringbuilder_t builder; + + if (args_number > 1) + { + substitutions = args + 1; + number_of_substitutions = args_number - 1; + } + else + { + substitutions = NULL; + number_of_substitutions = 0; + } + + /* 3. */ + ecma_value_t templated = args_number > 0 ? args[0] : ECMA_VALUE_UNDEFINED; + + ecma_value_t cooked = ecma_op_to_object (templated); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (cooked)) + { + return cooked; + } + + ecma_object_t *cooked_obj_p = ecma_get_object_from_value (cooked); + + /* 5. */ + ecma_value_t raw = ecma_op_object_get_by_magic_id (cooked_obj_p, LIT_MAGIC_STRING_RAW); + + ecma_deref_object (cooked_obj_p); + + if (ECMA_IS_VALUE_ERROR (raw)) + { + return raw; + } + + ecma_value_t raw_obj = ecma_op_to_object (raw); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (raw_obj)) + { + ecma_free_value (raw); + return raw_obj; + } + + ecma_object_t *raw_obj_p = ecma_get_object_from_value (raw_obj); + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 7 - 8. */ + ecma_length_t literal_segments; + if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (raw_obj_p, &literal_segments))) + { + goto cleanup; + } + + /* 9. */ + if (literal_segments == 0) + { + ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + goto cleanup; + } + + /* 10. */ + builder = ecma_stringbuilder_create (); + + /* 11. */ + next_index = 0; + + /* 12. */ + while (true) + { + /* 12.a,b */ + ecma_value_t next_seg = ecma_op_object_get_by_index (raw_obj_p, next_index); + + if (ECMA_IS_VALUE_ERROR (next_seg)) + { + goto builder_cleanup; + } + + ecma_string_t *next_seg_srt_p = ecma_op_to_string (next_seg); + + /* 12.c */ + if (JERRY_UNLIKELY (next_seg_srt_p == NULL)) + { + ecma_free_value (next_seg); + goto builder_cleanup; + } + + /* 12.d */ + ecma_stringbuilder_append (&builder, next_seg_srt_p); + + ecma_deref_ecma_string (next_seg_srt_p); + ecma_free_value (next_seg); + + /* 12.e */ + if (next_index + 1 == literal_segments) + { + ret_value = ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + goto cleanup; + } + + /* 12.f-g */ + if (next_index >= number_of_substitutions) + { + next_index++; + continue; + } + + /* 12.h */ + ecma_string_t *next_sub_p = ecma_op_to_string (substitutions[next_index]); + + /* 12.i */ + if (JERRY_UNLIKELY (next_sub_p == NULL)) + { + goto builder_cleanup; + } + + /* 12.j */ + ecma_stringbuilder_append (&builder, next_sub_p); + ecma_deref_ecma_string (next_sub_p); + + /* 12.k */ + next_index++; + } + +builder_cleanup: + ecma_stringbuilder_destroy (&builder); + +cleanup: + ecma_deref_object (raw_obj_p); + ecma_free_value (raw); + + return ret_value; +} /* ecma_builtin_string_object_raw */ + +/** + * The String object's 'fromCodePoint' routine + * + * See also: + * ECMA-262 v6, 21.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_object_from_code_point (const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (args_number == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + for (uint32_t index = 0; index < args_number; index++) + { + ecma_number_t to_number_num; + ecma_value_t to_number_value = ecma_op_to_number (args[index], &to_number_num); + + if (ECMA_IS_VALUE_ERROR (to_number_value)) + { + ecma_stringbuilder_destroy (&builder); + return to_number_value; + } + + if (!ecma_op_is_integer (to_number_num)) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_INVALID_CODE_POINT_ERROR); + } + + ecma_free_value (to_number_value); + + if (to_number_num < 0 || to_number_num > LIT_UNICODE_CODE_POINT_MAX) + { + ecma_stringbuilder_destroy (&builder); + return ecma_raise_range_error (ECMA_ERR_INVALID_CODE_POINT); + } + + lit_code_point_t code_point = (lit_code_point_t) to_number_num; + + ecma_char_t converted_cp[2]; + uint8_t encoded_size = lit_utf16_encode_code_point (code_point, converted_cp); + + for (uint8_t i = 0; i < encoded_size; i++) + { + ecma_stringbuilder_append_char (&builder, converted_cp[i]); + } + } + + ecma_string_t *ret_str_p = ecma_stringbuilder_finalize (&builder); + + return ecma_make_string_value (ret_str_p); +} /* ecma_builtin_string_object_from_code_point */ + +/** + * Handle calling [[Call]] of built-in String object + * + * See also: + * ECMA-262 v6, 21.1.1.1 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_string_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 1. */ + if (arguments_list_len == 0) + { + ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + /* 2.a */ + else if (ecma_is_value_symbol (arguments_list_p[0])) + { + ret_value = ecma_get_symbol_descriptive_string (arguments_list_p[0]); + } + /* 2.b */ + else + { + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ret_value = ecma_make_string_value (str_p); + } + + return ret_value; +} /* ecma_builtin_string_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in String object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_string_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_string_object (arguments_list_p, arguments_list_len); +} /* ecma_builtin_string_dispatch_construct */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_string_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (this_arg); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_STRING_OBJECT_FROM_CHAR_CODE: + { + return ecma_builtin_string_object_from_char_code (arguments_list_p, arguments_number); + } + case ECMA_BUILTIN_STRING_OBJECT_FROM_CODE_POINT: + { + return ecma_builtin_string_object_from_code_point (arguments_list_p, arguments_number); + } + case ECMA_BUILTIN_STRING_OBJECT_RAW: + { + return ecma_builtin_string_object_raw (arguments_list_p, arguments_number); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_string_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_STRING */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h new file mode 100644 index 00000000..2178acf1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * String built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_STRING + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.7.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_STRING_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_STRING_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_FROM_CHAR_CODE_UL, ECMA_BUILTIN_STRING_OBJECT_FROM_CHAR_CODE, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_FROM_CODE_POINT_UL, ECMA_BUILTIN_STRING_OBJECT_FROM_CODE_POINT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_RAW, ECMA_BUILTIN_STRING_OBJECT_RAW, NON_FIXED, 1) + +#endif /* JERRY_BUILTIN_STRING */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.cpp new file mode 100644 index 00000000..df4c9d5f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.cpp @@ -0,0 +1,111 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-symbol-object.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_SYMBOL_PROTOTYPE_ROUTINE_START = 0, + ECMA_SYMBOL_PROTOTYPE_VALUE_OF, /**< ECMA-262 v11, 19.4.3.4 */ + ECMA_SYMBOL_PROTOTYPE_TO_PRIMITIVE, /**< ECMA-262 v11, 19.4.3.5 */ + ECMA_SYMBOL_PROTOTYPE_TO_STRING, /**< ECMA-262 v11, 19.4.3.3 */ + ECMA_SYMBOL_PROTOTYPE_DESCRIPTION, /**< ECMA-262 v11, 19.4.3.2 */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID symbol_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup symbolprototype ECMA Symbol prototype object built-in + * @{ + */ + +/** + * Dispatcher of the Symbol built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_symbol_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list, arguments_number); + + ecma_value_t sym = ecma_symbol_this_value (this_arg); + + if (ECMA_IS_VALUE_ERROR (sym)) + { + return sym; + } + + if (builtin_routine_id < ECMA_SYMBOL_PROTOTYPE_TO_STRING) + { + return ecma_copy_value (sym); + } + + if (builtin_routine_id == ECMA_SYMBOL_PROTOTYPE_TO_STRING) + { + return ecma_get_symbol_descriptive_string (sym); + } + + JERRY_ASSERT (builtin_routine_id == ECMA_SYMBOL_PROTOTYPE_DESCRIPTION); + ecma_string_t *symbol_p = ecma_get_symbol_from_value (sym); + ecma_value_t desc = ecma_get_symbol_description (symbol_p); + if (ecma_is_value_undefined (desc)) + { + return desc; + } + + ecma_string_t *desc_p = ecma_get_string_from_value (desc); + ecma_ref_ecma_string (desc_p); + return desc; +} /* ecma_builtin_symbol_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h new file mode 100644 index 00000000..9b0daa0c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Symbol prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SYMBOL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_SYMBOL_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_SYMBOL_PROTOTYPE_VALUE_OF, 0, 0) +ROUTINE_CONFIGURABLE_ONLY (LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, ECMA_SYMBOL_PROTOTYPE_TO_PRIMITIVE, 0, 1) + +/* ECMA-262 v6, 19.4.3.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_SYMBOL_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262, v11, 19.4.3.2 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_DESCRIPTION, ECMA_SYMBOL_PROTOTYPE_DESCRIPTION, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.cpp new file mode 100644 index 00000000..3ce75f9b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.cpp @@ -0,0 +1,253 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-literal-storage.h" +#include "ecma-objects.h" +#include "ecma-symbol-object.h" + +#include "jcontext.h" +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol.inc.h" +#define BUILTIN_UNDERSCORED_ID symbol +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup symbol ECMA Symbol object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Symbol object. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_symbol_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_symbol (arguments_list_p, arguments_list_len); +} /* ecma_builtin_symbol_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Symbol object. + * + * Symbol constructor is not intended to be used + * with the new operator or to be subclassed. + * + * See also: + * ECMA-262 v6, 19.4.1 + * @return ecma value + */ +ecma_value_t +ecma_builtin_symbol_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_SYMBOL_IS_NOT_A_CONSTRUCTOR); +} /* ecma_builtin_symbol_dispatch_construct */ + +/** + * Helper function for Symbol object's 'for' and `keyFor` + * routines common parts + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma-string */ +{ + ecma_string_t *string_p; + + bool is_for = ecma_is_value_string (value_to_find); + + if (is_for) + { + string_p = ecma_get_string_from_value (value_to_find); + } + else + { + string_p = ecma_get_symbol_from_value (value_to_find); + } + + jmem_cpointer_t symbol_list_cp = JERRY_CONTEXT (symbol_list_first_cp); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (symbol_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, symbol_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (symbol_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, symbol_list_p->values[i]); + + if (is_for) + { + ecma_value_t symbol_desc = ecma_get_symbol_description (value_p); + + if (ecma_is_value_undefined (symbol_desc)) + { + ecma_ref_ecma_string (value_p); + return ecma_make_symbol_value (value_p); + } + + ecma_string_t *symbol_desc_p = ecma_get_string_from_value (symbol_desc); + + if (ecma_compare_ecma_strings (symbol_desc_p, string_p)) + { + /* The current symbol's descriptor matches with the value_to_find, + so the value is no longer needed. */ + ecma_deref_ecma_string (string_p); + return ecma_copy_value (ecma_make_symbol_value (value_p)); + } + } + else + { + if (string_p == value_p) + { + ecma_value_t symbol_desc = ecma_get_symbol_description (string_p); + + if (ecma_is_value_undefined (symbol_desc)) + { + return symbol_desc; + } + + ecma_string_t *symbol_desc_p = ecma_get_string_from_value (symbol_desc); + ecma_ref_ecma_string (symbol_desc_p); + return symbol_desc; + } + } + } + else + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = symbol_list_p->values + i; + } + } + } + + symbol_list_cp = symbol_list_p->next_cp; + } + + if (!is_for) + { + return ECMA_VALUE_UNDEFINED; + } + + /* There was no matching, sp a new symbol should be added the the global symbol list. The symbol creation requires + an extra reference to the descriptor string, but this reference has already been added. */ + ecma_string_t *new_symbol_p = ecma_new_symbol_from_descriptor_string (value_to_find); + + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, new_symbol_p); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + new_item_p->next_cp = JERRY_CONTEXT (symbol_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (symbol_list_first_cp), new_item_p); + + return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); +} /* ecma_builtin_symbol_for_helper */ + +/** + * The Symbol object's 'for' routine + * + * See also: + * ECMA-262 v6, 19.4.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_for (ecma_value_t this_arg, /**< this argument */ + ecma_value_t key) /**< key string */ +{ + JERRY_UNUSED (this_arg); + ecma_string_t *string_desc_p = ecma_op_to_string (key); + + /* 1. */ + if (JERRY_UNLIKELY (string_desc_p == NULL)) + { + /* 2. */ + return ECMA_VALUE_ERROR; + } + + return ecma_builtin_symbol_for_helper (ecma_make_string_value (string_desc_p)); +} /* ecma_builtin_symbol_for */ + +/** + * The Symbol object's 'keyFor' routine + * + * See also: + * ECMA-262 v6, 19.4.2. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_key_for (ecma_value_t this_arg, /**< this argument */ + ecma_value_t symbol) /**< symbol */ +{ + JERRY_UNUSED (this_arg); + + /* 1. */ + if (!ecma_is_value_symbol (symbol)) + { + return ecma_raise_type_error (ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL); + } + + /* 2-4. */ + return ecma_builtin_symbol_for_helper (symbol); +} /* ecma_builtin_symbol_key_for */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h new file mode 100644 index 00000000..9fecbd4f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h @@ -0,0 +1,80 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Symbol built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 19.4.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SYMBOL_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 19.4.2.7 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* ECMA-262 v10, 19.4.2.1 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_ASYNC_ITERATOR, LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR) + +/* ECMA-262 v6, 19.4.2.2 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_HAS_INSTANCE, LIT_GLOBAL_SYMBOL_HAS_INSTANCE) + +/* ECMA-262 v6, 19.4.2.3 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE) + +/* ECMA-262 v6, 19.4.2.4 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_ITERATOR, LIT_GLOBAL_SYMBOL_ITERATOR) + +/* ECMA-262 v6, 19.4.2.6 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_MATCH, LIT_GLOBAL_SYMBOL_MATCH) + +/* ECMA-262 v6, 19.4.2.8 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_REPLACE, LIT_GLOBAL_SYMBOL_REPLACE) + +/* ECMA-262 v6, 19.4.2.9 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SEARCH, LIT_GLOBAL_SYMBOL_SEARCH) + +/* ECMA-262 v6, 19.4.2.10 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SPECIES, LIT_GLOBAL_SYMBOL_SPECIES) + +/* ECMA-262 v6, 19.4.2.11 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SPLIT, LIT_GLOBAL_SYMBOL_SPLIT) + +/* ECMA-262 v6, 19.4.2.12 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_PRIMITIVE, LIT_GLOBAL_SYMBOL_TO_PRIMITIVE) + +/* ECMA-262 v6, 19.4.2.13 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_STRING_TAG, LIT_GLOBAL_SYMBOL_TO_STRING_TAG) + +/* ECMA-262 v6, 19.4.2.14 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_UNSCOPABLES, LIT_GLOBAL_SYMBOL_UNSCOPABLES) + +/* ECMA-262 v11, 19.4.2.8 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_MATCH_ALL, LIT_GLOBAL_SYMBOL_MATCH_ALL) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_FOR, ecma_builtin_symbol_for, 1, 1) +ROUTINE (LIT_MAGIC_STRING_KEY_FOR, ecma_builtin_symbol_key_for, 1, 1) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.cpp new file mode 100644 index 00000000..2e5e7b8c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-syntaxerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID syntax_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h new file mode 100644 index 00000000..670efc1d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SyntaxError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_SYNTAX_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SYNTAX_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.cpp new file mode 100644 index 00000000..449c0db6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-syntaxerror.inc.h" +#define BUILTIN_UNDERSCORED_ID syntax_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup syntaxerror ECMA SyntaxError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in SyntaxError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_syntax_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_SYNTAX, arguments_list_p, arguments_list_len); +} /* ecma_builtin_syntax_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in SyntaxError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_syntax_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_syntax_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_syntax_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h new file mode 100644 index 00000000..bee730cf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * SyntaxError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_SYNTAX_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.cpp new file mode 100644 index 00000000..253a8deb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.cpp @@ -0,0 +1,82 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-type-error-thrower.inc.h" +#define BUILTIN_UNDERSCORED_ID type_error_thrower +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup type_error_thrower ECMA [[ThrowTypeError]] object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in [[ThrowTypeError]] object + * + * See also: + * ECMA-262 v5, 13.2.3 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_thrower_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CANNOT_ACCESS_CALLER_CALLE_ARGUMENTS); +} /* ecma_builtin_type_error_thrower_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in [[ThrowTypeError]] object + * + * See also: + * ECMA-262 v5, 13.2.3 + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_thrower_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_builtin_type_error_thrower_dispatch_call (arguments_list_p, arguments_list_len); +} /* ecma_builtin_type_error_thrower_dispatch_construct */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h new file mode 100644 index 00000000..e44c8aba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h @@ -0,0 +1,31 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * [[ThrowTypeError]] description + * + * See also: ECMA-262 v5, 13.2.3 + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FIXED) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.cpp new file mode 100644 index 00000000..9e9971a1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typeerror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID type_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h new file mode 100644 index 00000000..4d0b4f28 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * TypeError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_TYPE_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_TYPE_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.cpp new file mode 100644 index 00000000..c18cdaad --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typeerror.inc.h" +#define BUILTIN_UNDERSCORED_ID type_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup typeerror ECMA TypeError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in TypeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_TYPE, arguments_list_p, arguments_list_len); +} /* ecma_builtin_type_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in TypeError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_type_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_type_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_type_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h new file mode 100644 index 00000000..d2bb8e33 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * TypeError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_TYPE_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.cpp new file mode 100644 index 00000000..26acbaba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.cpp @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-urierror-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uri_error_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h new file mode 100644 index 00000000..2b6fd89c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * UriError.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.7.8 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_URI_ERROR, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.9 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_URI_ERROR_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v5, 15.11.7.10 */ +STRING_VALUE (LIT_MAGIC_STRING_MESSAGE, LIT_MAGIC_STRING__EMPTY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.cpp new file mode 100644 index 00000000..1c7333e9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.cpp @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_BUILTIN_ERRORS + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-urierror.inc.h" +#define BUILTIN_UNDERSCORED_ID uri_error +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup urierror ECMA UriError object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in UriError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uri_error_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_builtin_helper_error_dispatch_call (JERRY_ERROR_URI, arguments_list_p, arguments_list_len); +} /* ecma_builtin_uri_error_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in UriError object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uri_error_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_uri_error_dispatch_call (arguments_list_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + ecma_object_t *object_p = ecma_get_object_from_value (result); + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p); + } + + ecma_deref_object (proto_p); + + return result; +} /* ecma_builtin_uri_error_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ERRORS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h new file mode 100644 index 00000000..ed1d3d5a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * UriError built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_ERRORS + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v5, 15.11.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_URI_ERROR_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_ERRORS */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.cpp new file mode 100644 index 00000000..2a8d6768 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.cpp @@ -0,0 +1,65 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakmap-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID weakmap_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakmap ECMA WeakMap object built-in + * @{ + */ +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_weakmap_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_WEAKMAP_UL); +} /* ecma_builtin_weakmap_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h new file mode 100644 index 00000000..75d61770 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h @@ -0,0 +1,42 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakMap.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.3.3.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_WEAKMAP, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.3.3.6 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_WEAKMAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE_WEAK, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET, ECMA_CONTAINER_ROUTINE_GET, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_CONTAINER_ROUTINE_SET, 2, 2) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.cpp new file mode 100644 index 00000000..afc2f667 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.cpp @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakmap.inc.h" +#define BUILTIN_UNDERSCORED_ID weakmap +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakmap ECMA WeakMap object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in WeakMap object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakmap_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_WEAKMAP_REQUIRES_NEW); +} /* ecma_builtin_weakmap_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in WeakMap object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakmap_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_WEAKMAP_UL, + ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE); +} /* ecma_builtin_weakmap_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.inc.h new file mode 100644 index 00000000..8bf9843f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakmap.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakMap built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.3.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_WEAKMAP_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.3.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.cpp new file mode 100644 index 00000000..4b4caf26 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.cpp @@ -0,0 +1,114 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_WEAKREF + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_ROUTINE_START = 0, + ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_DEREF +}; + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakref-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID weakref_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakref ECMA WeakRef object built-in + * @{ + */ + +/** + * Deref checks weakRef target + * + * @return weakRef target + * error - otherwise + */ +static ecma_value_t +ecma_builtin_weakref_prototype_object_deref (ecma_value_t this_arg) /**< this argument */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_OBJECT); + } + + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + ecma_extended_object_t *this_ext_obj = (ecma_extended_object_t *) object_p; + + if (!ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_WEAKREF)) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_IS_NOT_WEAKREF); + } + + return ecma_copy_value (this_ext_obj->u.cls.u3.target); +} /* ecma_builtin_weakref_prototype_object_deref */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_weakref_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED_2 (arguments_list_p, arguments_number); + + switch (builtin_routine_id) + { + case ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_DEREF: + { + return ecma_builtin_weakref_prototype_object_deref (this_arg); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_weakref_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_WEAKREF */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.inc.h new file mode 100644 index 00000000..533d3956 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref-prototype.inc.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakSet.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_WEAKREF + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_WEAKREF, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_WEAKREF_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_DEREF, ECMA_BUILTIN_WEAKREF_PROTOTYPE_OBJECT_DEREF, 0, 0) + +#endif /* JERRY_BUILTIN_WEAKREF */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.cpp new file mode 100644 index 00000000..bf15aae1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.cpp @@ -0,0 +1,96 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_WEAKREF + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakref.inc.h" +#define BUILTIN_UNDERSCORED_ID weakref +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakref ECMA WeakRef object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in WeakRef object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakref_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_WEAKREF_REQUIRES_NEW); +} /* ecma_builtin_weakref_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in WeakRef object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakref_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (arguments_list_len == 0 || !ecma_is_value_object (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_WEAKREF_TARGET_MUST_BE_AN_OBJECT); + } + + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) != NULL); + + ecma_object_t *proto_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (proto_p); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.cls.type = ECMA_OBJECT_CLASS_WEAKREF; + ext_obj_p->u.cls.u3.target = arguments_list_p[0]; + ecma_op_object_set_weak (ecma_get_object_from_value (arguments_list_p[0]), object_p); + + return ecma_make_object_value (object_p); +} /* ecma_builtin_weakref_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_WEAKREF */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.inc.h new file mode 100644 index 00000000..d4e6e5b5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakref.inc.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakRef built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_WEAKREF + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_WEAKREF_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_WEAKREF */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.cpp new file mode 100644 index 00000000..370c5047 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.cpp @@ -0,0 +1,67 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-container-object.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakset-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID weakset_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakset ECMA WeakSet object built-in + * @{ + */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_weakset_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + return ecma_builtin_container_dispatch_routine (builtin_routine_id, + this_arg, + arguments_list_p, + LIT_MAGIC_STRING_WEAKSET_UL); +} /* ecma_builtin_weakset_prototype_dispatch_routine */ +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h new file mode 100644 index 00000000..6221f895 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakSet.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.4.3.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_WEAKSET, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ECMA-262 v6, 23.4.3.5 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, LIT_MAGIC_STRING_WEAKSET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_ADD, ECMA_CONTAINER_ROUTINE_ADD, 1, 1) +ROUTINE (LIT_MAGIC_STRING_DELETE, ECMA_CONTAINER_ROUTINE_DELETE_WEAK, 1, 1) +ROUTINE (LIT_MAGIC_STRING_HAS, ECMA_CONTAINER_ROUTINE_HAS, 1, 1) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.cpp new file mode 100644 index 00000000..f30c6c25 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.cpp @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-container-object.h" +#include "ecma-exceptions.h" + +#if JERRY_BUILTIN_CONTAINER + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-weakset.inc.h" +#define BUILTIN_UNDERSCORED_ID weakset +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup weakset ECMA WeakSet object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in WeakSet object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakset_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_WEAKSET_REQUIRES_NEW); +} /* ecma_builtin_weakset_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in WeakSet object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_weakset_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_container_create (arguments_list_p, + arguments_list_len, + LIT_MAGIC_STRING_WEAKSET_UL, + ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE); +} /* ecma_builtin_weakset_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.inc.h new file mode 100644 index 00000000..8aa16c84 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-weakset.inc.h @@ -0,0 +1,41 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * WeakSet built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_CONTAINER + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.4.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.4 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_WEAKSET_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.4.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE, ECMA_PROPERTY_FIXED) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h new file mode 100644 index 00000000..5695e2d8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h @@ -0,0 +1,98 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTINS_INTERNAL_H +#define ECMA_BUILTINS_INTERNAL_H + +#ifndef ECMA_BUILTINS_INTERNAL +#error "!ECMA_BUILTINS_INTERNAL" +#endif /* !ECMA_BUILTINS_INTERNAL */ + +#include "ecma-builtins.h" +#include "ecma-globals.h" + +/** + * Type of built-in properties. + */ +typedef enum +{ + ECMA_BUILTIN_PROPERTY_SIMPLE, /**< simple value property */ + ECMA_BUILTIN_PROPERTY_NUMBER, /**< number value property */ + ECMA_BUILTIN_PROPERTY_STRING, /**< string value property */ + ECMA_BUILTIN_PROPERTY_SYMBOL, /**< symbol value property */ + ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY, /**< intrinsic routine property */ + ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION, /**< full accessor property with builtin function object + getter/setter pair */ + ECMA_BUILTIN_PROPERTY_OBJECT, /**< builtin object property */ + ECMA_BUILTIN_PROPERTY_ROUTINE, /**< routine property */ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE, /**< full accessor property */ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, /**< read-only accessor property */ + ECMA_BUILTIN_PROPERTY_END, /**< last property */ +} ecma_builtin_property_type_t; + +/** + * Type of symbolic built-in number types (starting from 256). + */ +typedef enum +{ + ECMA_BUILTIN_NUMBER_MAX = 256, /**< value of ECMA_NUMBER_MAX_VALUE */ + ECMA_BUILTIN_NUMBER_MIN, /**< value of ECMA_NUMBER_MIN_VALUE */ + ECMA_BUILTIN_NUMBER_EPSILON, /**< value of ECMA_NUMBER_EPSILON */ + ECMA_BUILTIN_NUMBER_MAX_SAFE_INTEGER, /**< value of ECMA_NUMBER_MAX_SAFE_INTEGER */ + ECMA_BUILTIN_NUMBER_MIN_SAFE_INTEGER, /**< value of ECMA_NUMBER_MIN_SAFE_INTEGER */ + ECMA_BUILTIN_NUMBER_E, /**< value of ECMA_NUMBER_E */ + ECMA_BUILTIN_NUMBER_PI, /**< value of ECMA_NUMBER_PI */ + ECMA_BUILTIN_NUMBER_LN10, /**< value of ECMA_NUMBER_LN10 */ + ECMA_BUILTIN_NUMBER_LN2, /**< value of ECMA_NUMBER_LN2 */ + ECMA_BUILTIN_NUMBER_LOG2E, /**< value of ECMA_NUMBER_LOG2E */ + ECMA_BUILTIN_NUMBER_LOG10E, /**< value of ECMA_NUMBER_LOG10E */ + ECMA_BUILTIN_NUMBER_SQRT2, /**< value of ECMA_NUMBER_SQRT2 */ + ECMA_BUILTIN_NUMBER_SQRT_1_2, /**< value of ECMA_NUMBER_SQRT_1_2 */ + ECMA_BUILTIN_NUMBER_NAN, /**< result of ecma_number_make_nan () */ + ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY, /**< result of ecma_number_make_infinity (false) */ + ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY, /**< result of ecma_number_make_infinity (true) */ +} ecma_builtin_number_type_t; + +/** + * Description of built-in properties. + */ +typedef struct +{ + uint16_t magic_string_id; /**< name of the property */ + uint8_t type; /**< type of the property */ + uint8_t attributes; /**< attributes of the property */ + uint16_t value; /**< value of the property */ +} ecma_builtin_property_descriptor_t; + +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + extern const ecma_builtin_property_descriptor_t ecma_builtin_##lowercase_name##_property_descriptor_list[]; \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_call (const ecma_value_t *, uint32_t); \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_construct (const ecma_value_t *, uint32_t); \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_routine (uint8_t builtin_routine_id, \ + ecma_value_t this_arg_value, \ + const ecma_value_t[], \ + uint32_t); +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + extern const ecma_builtin_property_descriptor_t ecma_builtin_##lowercase_name##_property_descriptor_list[]; \ + ecma_value_t ecma_builtin_##lowercase_name##_dispatch_routine (uint8_t builtin_routine_id, \ + ecma_value_t this_arg_value, \ + const ecma_value_t[], \ + uint32_t); +#include "ecma-builtins.inc.h" + +#undef BUILTIN_ROUTINE +#undef BUILTIN + +#endif /* !ECMA_BUILTINS_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.cpp new file mode 100644 index 00000000..cae35ad8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.cpp @@ -0,0 +1,1524 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#include "ecma-alloc.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt-bit-fields.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + */ + +JERRY_STATIC_ASSERT ((((int)ECMA_BUILTIN_ID_GLOBAL) == ((int)ECMA_BUILTIN_OBJECTS_COUNT)), + ecma_builtin_id_global_must_be_the_last_builtin_id); + +/** + * Checks whether the built-in is an ecma_extended_built_in_object_t + */ +#define ECMA_BUILTIN_IS_EXTENDED_BUILT_IN(object_type) \ + ((object_type) == ECMA_OBJECT_TYPE_BUILT_IN_CLASS || (object_type) == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY) + +/** + * Helper definition for ecma_builtin_property_list_references. + */ +typedef const ecma_builtin_property_descriptor_t *ecma_builtin_property_list_reference_t; + +/** + * Definition of built-in dispatch routine function pointer. + */ +typedef ecma_value_t (*ecma_builtin_dispatch_routine_t) (uint8_t builtin_routine_id, + ecma_value_t this_arg, + const ecma_value_t arguments_list[], + uint32_t arguments_number); +/** + * Definition of built-in dispatch call function pointer. + */ +typedef ecma_value_t (*ecma_builtin_dispatch_call_t) (const ecma_value_t arguments_list[], uint32_t arguments_number); +/** + * Definition of a builtin descriptor which contains the builtin object's: + * - prototype objects's id (13-bits) + * - type (3-bits) + * + * Layout: + * + * |----------------------|---------------| + * prototype_id(12) obj_type(4) + */ +typedef uint16_t ecma_builtin_descriptor_t; + +/** + * Bitshift index for get the prototype object's id from a builtin descriptor + */ +#define ECMA_BUILTIN_PROTOTYPE_ID_SHIFT 4 + +/** + * Bitmask for get the object's type from a builtin descriptor + */ +#define ECMA_BUILTIN_OBJECT_TYPE_MASK ((1 << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) - 1) + +/** + * Create a builtin descriptor value + */ +#define ECMA_MAKE_BUILTIN_DESCRIPTOR(type, proto_id) (((proto_id) << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) | (type)) + +/** + * List of the built-in descriptors. + */ +static const ecma_builtin_descriptor_t ecma_builtin_descriptors[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id), +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id), +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + /** @endcond */ +}; + +#ifndef JERRY_NDEBUG +/** @cond doxygen_suppress */ +enum +{ + ECMA_BUILTIN_EXTENSIBLE_CHECK = +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) && +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) && +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + true +}; +/** @endcond */ + +/** + * All the builtin object must be extensible except the ThrowTypeError object. + */ +JERRY_STATIC_ASSERT (ECMA_BUILTIN_EXTENSIBLE_CHECK == true, + ecma_builtin_must_be_extensible_except_the_builtin_thorw_type_error_object); +#endif /* !JERRY_NDEBUG */ + +/** + * List of the built-in routines. + */ +static const ecma_builtin_dispatch_routine_t ecma_builtin_routines[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_routine, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_routine, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + /** @endcond */ +}; + +/** + * List of the built-in call functions. + */ +static const ecma_builtin_dispatch_call_t ecma_builtin_call_functions[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_call, +#include "ecma-builtins.inc.h" +#undef BUILTIN_ROUTINE +#undef BUILTIN + /** @endcond */ +}; + +/** + * List of the built-in construct functions. + */ +static const ecma_builtin_dispatch_call_t ecma_builtin_construct_functions[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_dispatch_construct, +#include "ecma-builtins.inc.h" +#undef BUILTIN_ROUTINE +#undef BUILTIN + /** @endcond */ +}; + +/** + * Property descriptor lists for all built-ins. + */ +static const ecma_builtin_property_list_reference_t ecma_builtin_property_list_references[] = { +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_property_descriptor_list, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) \ + ecma_builtin_##lowercase_name##_property_descriptor_list, +#include "ecma-builtins.inc.h" +#undef BUILTIN_ROUTINE +#undef BUILTIN + /** @endcond */ +}; + +/** + * Get the number of properties of a built-in object. + * + * @return the number of properties + */ +static size_t +ecma_builtin_get_property_count (ecma_builtin_id_t builtin_id) /**< built-in ID */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) + { + curr_property_p++; + } + + return (size_t) (curr_property_p - property_list_p); +} /* ecma_builtin_get_property_count */ + +/** + * Check if passed object is a global built-in. + * + * @return true - if the object is a global built-in + * false - otherwise + */ +bool +ecma_builtin_is_global (ecma_object_t *object_p) /**< pointer to an object */ +{ + return (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL + && ((ecma_extended_object_t *) object_p)->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL); +} /* ecma_builtin_is_global */ + +/** + * Get reference to the global object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the global object + */ +ecma_object_t * +ecma_builtin_get_global (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (global_object_p) != NULL); + + return (ecma_object_t *) JERRY_CONTEXT (global_object_p); +} /* ecma_builtin_get_global */ + +/** + * Checks whether the given function is a built-in routine + * + * @return true - if the function object is a built-in routine + * false - otherwise + */ +bool +ecma_builtin_function_is_routine (ecma_object_t *func_obj_p) /**< function object */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + return (ext_func_obj_p->u.built_in.routine_id != 0); +} /* ecma_builtin_function_is_routine */ + +#if JERRY_BUILTIN_REALMS + +/** + * Get reference to the realm provided by another built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the global object + */ +static ecma_global_object_t * +ecma_builtin_get_realm (ecma_object_t *builtin_object_p) /**< built-in object */ +{ + ecma_object_type_t object_type = ecma_get_object_type (builtin_object_p); + ecma_value_t realm_value; + + JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY || object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + realm_value = ((ecma_extended_built_in_object_t *) builtin_object_p)->built_in.realm_value; + } + else + { + realm_value = ((ecma_extended_object_t *) builtin_object_p)->u.built_in.realm_value; + } + + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); +} /* ecma_builtin_get_realm */ + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * Instantiate specified ECMA built-in object + * + * @return the newly instantiated built-in + */ +static ecma_object_t * +ecma_instantiate_builtin (ecma_global_object_t *global_object_p, /**< global object */ + ecma_builtin_id_t obj_builtin_id) /**< built-in id */ +{ + jmem_cpointer_t *builtin_objects = global_object_p->builtin_objects; + + JERRY_ASSERT (obj_builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + JERRY_ASSERT (builtin_objects[obj_builtin_id] == JMEM_CP_NULL); + + ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[obj_builtin_id]; + ecma_builtin_id_t object_prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT); + + ecma_object_t *prototype_obj_p; + + if (JERRY_UNLIKELY (object_prototype_builtin_id == ECMA_BUILTIN_ID__COUNT)) + { + prototype_obj_p = NULL; + } + else + { + if (builtin_objects[object_prototype_builtin_id] == JMEM_CP_NULL) + { + ecma_instantiate_builtin (global_object_p, object_prototype_builtin_id); + } + prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_objects[object_prototype_builtin_id]); + JERRY_ASSERT (prototype_obj_p != NULL); + } + + ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK); + + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || obj_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY || obj_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + bool is_extended_built_in = ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (obj_type); + + size_t ext_object_size = + (is_extended_built_in ? sizeof (ecma_extended_built_in_object_t) : sizeof (ecma_extended_object_t)); + + size_t property_count = ecma_builtin_get_property_count (obj_builtin_id); + + if (property_count > ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE) + { + /* Only 64 extra properties supported at the moment. + * This can be extended to 256 later. */ + JERRY_ASSERT (property_count <= (ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 64)); + + ext_object_size += sizeof (uint64_t); + } + + ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, ext_object_size, obj_type); + + if (JERRY_UNLIKELY (obj_builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER)) + { + ecma_op_ordinary_object_prevent_extensions (obj_p); + } + else + { + ecma_op_ordinary_object_set_extensible (obj_p); + } + + /* + * [[Class]] property of built-in object is not stored explicitly. + * + * See also: ecma_object_get_class_name + */ + + ecma_built_in_props_t *built_in_props_p; + + if (is_extended_built_in) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) obj_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) obj_p)->u.built_in; + } + + built_in_props_p->id = (uint8_t) obj_builtin_id; + built_in_props_p->routine_id = 0; + built_in_props_p->u.length_and_bitset_size = 0; + built_in_props_p->u2.instantiated_bitset[0] = 0; +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (built_in_props_p->realm_value, global_object_p); +#else /* !JERRY_BUILTIN_REALMS */ + built_in_props_p->continue_instantiated_bitset[0] = 0; +#endif /* JERRY_BUILTIN_REALMS */ + + if (property_count > ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE) + { + built_in_props_p->u.length_and_bitset_size = 1 << ECMA_BUILT_IN_BITSET_SHIFT; + + uint32_t *instantiated_bitset_p = (uint32_t *) (built_in_props_p + 1); + instantiated_bitset_p[0] = 0; + instantiated_bitset_p[1] = 0; + } + + /** Initializing [[PrimitiveValue]] properties of built-in prototype objects */ + switch (obj_builtin_id) + { +#if JERRY_BUILTIN_ARRAY + case ECMA_BUILTIN_ID_ARRAY_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.array.length = 0; + ext_object_p->u.array.length_prop_and_hole_count = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_VIRTUAL; + break; + } +#endif /* JERRY_BUILTIN_ARRAY */ + +#if JERRY_BUILTIN_STRING + case ECMA_BUILTIN_ID_STRING_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_STRING; + ext_object_p->u.cls.u3.value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + break; + } +#endif /* JERRY_BUILTIN_STRING */ + +#if JERRY_BUILTIN_NUMBER + case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_NUMBER; + ext_object_p->u.cls.u3.value = ecma_make_integer_value (0); + break; + } +#endif /* JERRY_BUILTIN_NUMBER */ + +#if JERRY_BUILTIN_BOOLEAN + case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE: + { + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_BOOLEAN; + ext_object_p->u.cls.u3.value = ECMA_VALUE_FALSE; + break; + } +#endif /* JERRY_BUILTIN_BOOLEAN */ + + default: + { + JERRY_ASSERT (obj_type != ECMA_OBJECT_TYPE_BUILT_IN_CLASS); + break; + } + } + + ECMA_SET_NON_NULL_POINTER (builtin_objects[obj_builtin_id], obj_p); + ecma_deref_object (obj_p); + return obj_p; +} /* ecma_instantiate_builtin */ + +/** + * Create a global object + * + * @return a new global object + */ +ecma_global_object_t * +ecma_builtin_create_global_object (void) +{ + ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[ECMA_BUILTIN_ID_GLOBAL]; + ecma_builtin_id_t prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT); + ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK); + size_t property_count = ecma_builtin_get_property_count (ECMA_BUILTIN_ID_GLOBAL); + + JERRY_ASSERT (prototype_builtin_id != ECMA_BUILTIN_ID__COUNT); + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL); + + /* Whenever this assertion fails, the size of extra_instantiated_bitset in ecma_global_object_t + * must be increased and 32 must be added to these constants. Furthermore the new uint32 item + * must be set to zero. */ +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (property_count <= ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 64); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_ASSERT (property_count <= ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 32); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *object_p = ecma_create_object (NULL, sizeof (ecma_global_object_t), obj_type); + + ecma_op_ordinary_object_set_extensible (object_p); + + ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p; + + global_object_p->extended_object.u.built_in.id = (uint8_t) ECMA_BUILTIN_ID_GLOBAL; + global_object_p->extended_object.u.built_in.routine_id = 0; + /* Bitset size is ignored by the gc. */ + global_object_p->extended_object.u.built_in.u.length_and_bitset_size = 0; + global_object_p->extended_object.u.built_in.u2.instantiated_bitset[0] = 0; + global_object_p->extra_instantiated_bitset[0] = 0; +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (global_object_p->extended_object.u.built_in.realm_value, global_object_p); + global_object_p->extra_realms_bitset = 0; + global_object_p->this_binding = ecma_make_object_value (object_p); +#else /* !JERRY_BUILTIN_REALMS */ + global_object_p->extended_object.u.built_in.continue_instantiated_bitset[0] = 0; +#endif /* JERRY_BUILTIN_REALMS */ + + memset (global_object_p->builtin_objects, 0, (sizeof (jmem_cpointer_t) * ECMA_BUILTIN_OBJECTS_COUNT)); + + /* Temporary self reference for GC mark. */ + ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, object_p); + global_object_p->global_scope_cp = global_object_p->global_env_cp; + + ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL, object_p); + + ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p); + global_object_p->global_scope_cp = global_object_p->global_env_cp; + + ecma_deref_object (global_lex_env_p); + + ecma_object_t *prototype_object_p; + prototype_object_p = ecma_instantiate_builtin (global_object_p, prototype_builtin_id); + JERRY_ASSERT (prototype_object_p != NULL); + + ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, prototype_object_p); + + return global_object_p; +} /* ecma_builtin_create_global_object */ + +/** + * Get reference to specified built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + + ecma_global_object_t *global_object_p = (ecma_global_object_t *) ecma_builtin_get_global (); + jmem_cpointer_t *builtin_p = global_object_p->builtin_objects + builtin_id; + + if (JERRY_UNLIKELY (*builtin_p == JMEM_CP_NULL)) + { + return ecma_instantiate_builtin (global_object_p, builtin_id); + } + + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p); +} /* ecma_builtin_get */ + +#if JERRY_BUILTIN_REALMS + +/** + * Get reference to specified built-in object using the realm provided by another built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_builtin_get_from_realm (ecma_global_object_t *global_object_p, /**< global object */ + ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + + jmem_cpointer_t *builtin_p = global_object_p->builtin_objects + builtin_id; + + if (JERRY_UNLIKELY (*builtin_p == JMEM_CP_NULL)) + { + return ecma_instantiate_builtin (global_object_p, builtin_id); + } + + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p); +} /* ecma_builtin_get_from_realm */ + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * Get reference to specified built-in object using the realm provided by another built-in object + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to the object's instance + */ +static inline ecma_object_t * +ecma_builtin_get_from_builtin (ecma_object_t *builtin_object_p, /**< built-in object */ + ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT); + +#if JERRY_BUILTIN_REALMS + return ecma_builtin_get_from_realm (ecma_builtin_get_realm (builtin_object_p), builtin_id); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_UNUSED (builtin_object_p); + return ecma_builtin_get (builtin_id); +#endif /* JERRY_BUILTIN_REALMS */ +} /* ecma_builtin_get_from_builtin */ + +/** + * Construct a Function object for specified built-in routine + * + * See also: ECMA-262 v5, 15 + * + * @return pointer to constructed Function object + */ +static ecma_object_t * +ecma_builtin_make_function_object_for_routine (ecma_object_t *builtin_object_p, /**< builtin object */ + uint8_t routine_id, /**< builtin-wide identifier of the built-in + * object's routine property */ + uint32_t routine_index, /**< property descriptor index of routine */ + uint8_t flags) /**< see also: ecma_builtin_routine_flags */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get_from_builtin (builtin_object_p, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + + size_t ext_object_size = sizeof (ecma_extended_object_t); + + ecma_object_t *func_obj_p = ecma_create_object (prototype_obj_p, ext_object_size, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + JERRY_ASSERT (routine_id > 0); + JERRY_ASSERT (routine_index <= UINT8_MAX); + + ecma_built_in_props_t *built_in_props_p; + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (ecma_get_object_type (builtin_object_p))) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) builtin_object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) builtin_object_p)->u.built_in; + } + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + ext_func_obj_p->u.built_in.id = built_in_props_p->id; + ext_func_obj_p->u.built_in.routine_id = routine_id; + ext_func_obj_p->u.built_in.u.routine_index = (uint8_t) routine_index; + ext_func_obj_p->u.built_in.u2.routine_flags = flags; + +#if JERRY_BUILTIN_REALMS + ext_func_obj_p->u.built_in.realm_value = built_in_props_p->realm_value; +#endif /* JERRY_BUILTIN_REALMS */ + + return func_obj_p; +} /* ecma_builtin_make_function_object_for_routine */ + +/** + * Construct a Function object for specified built-in accessor getter + * + * @return pointer to constructed accessor getter Function object + */ +static ecma_object_t * +ecma_builtin_make_function_object_for_getter_accessor (ecma_object_t *builtin_object_p, /**< builtin object */ + uint8_t routine_id, /**< builtin-wide id of the built-in + * object's routine property */ + uint32_t routine_index) /**< property descriptor index + * of routine */ +{ + return ecma_builtin_make_function_object_for_routine (builtin_object_p, + routine_id, + routine_index, + ECMA_BUILTIN_ROUTINE_GETTER); +} /* ecma_builtin_make_function_object_for_getter_accessor */ + +/** + * Construct a Function object for specified built-in accessor setter + * + * @return pointer to constructed accessor getter Function object + */ +static ecma_object_t * +ecma_builtin_make_function_object_for_setter_accessor (ecma_object_t *builtin_object_p, /**< builtin object */ + uint8_t routine_id, /**< builtin-wide id of the built-in + * object's routine property */ + uint32_t routine_index) /**< property descriptor index + * of routine */ +{ + return ecma_builtin_make_function_object_for_routine (builtin_object_p, + routine_id, + routine_index, + ECMA_BUILTIN_ROUTINE_SETTER); +} /* ecma_builtin_make_function_object_for_setter_accessor */ + +/** + * Create specification defined properties for built-in native handlers. + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +static ecma_property_t * +ecma_builtin_native_handler_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ecma_property_t *prop_p = NULL; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED) == 0) + { + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &prop_p); + + value_p->value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + } + else if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED) == 0) + { + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &prop_p); + + const uint8_t length = ecma_builtin_handler_get_length ((ecma_native_handler_id_t) ext_obj_p->u.built_in.routine_id); + value_p->value = ecma_make_integer_value (length); + } + } + + return prop_p; +} /* ecma_builtin_native_handler_try_to_instantiate_property */ + +/** + * Lazy instantiation of builtin routine property of builtin object + * + * If the property is not instantiated yet, instantiate the property and + * return pointer to the instantiated property. + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + && ecma_builtin_function_is_routine (object_p)); + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + return ecma_builtin_native_handler_try_to_instantiate_property (object_p, property_name_p); + } + + if (ecma_string_is_length (property_name_p)) + { + /* + * Lazy instantiation of 'length' property + */ + ecma_property_t *len_prop_p; + + uint8_t *bitset_p = &ext_func_p->u.built_in.u2.routine_flags; + + if (*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED) + { + /* length property was already instantiated */ + return NULL; + } + + /* We mark that the property was lazily instantiated, + * as it is configurable and so can be deleted (ECMA-262 v6, 19.2.4.1) */ + ecma_property_value_t *len_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &len_prop_p); + + uint8_t length = 0; + + if (ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_SETTER) + { + length = 1; + } + else if (!(ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_GETTER)) + { + uint8_t routine_index = ext_func_p->u.built_in.u.routine_index; + const ecma_builtin_property_descriptor_t *property_list_p; + + property_list_p = ecma_builtin_property_list_references[ext_func_p->u.built_in.id]; + + JERRY_ASSERT (property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ROUTINE); + + length = ECMA_GET_ROUTINE_LENGTH (property_list_p[routine_index].value); + } + + len_prop_value_p->value = ecma_make_integer_value (length); + return len_prop_p; + } + + /* + * Lazy instantiation of 'name' property + */ + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + uint8_t *bitset_p = &ext_func_p->u.built_in.u2.routine_flags; + + if (*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED) + { + /* name property was already instantiated */ + return NULL; + } + + /* We mark that the property was lazily instantiated */ + ecma_property_t *name_prop_p; + ecma_property_value_t *name_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &name_prop_p); + + uint8_t routine_index = ext_func_p->u.built_in.u.routine_index; + const ecma_builtin_property_descriptor_t *property_list_p; + + property_list_p = ecma_builtin_property_list_references[ext_func_p->u.built_in.id]; + + JERRY_ASSERT (property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ROUTINE + || property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE + || property_list_p[routine_index].type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY); + + lit_magic_string_id_t name_id = (lit_magic_string_id_t) property_list_p[routine_index].magic_string_id; + ecma_string_t *name_p; + + if (JERRY_UNLIKELY (name_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + /* Note: Whenever new intrinsic routine is being added this mapping should be updated as well! */ + if (JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES) + || JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES) + || JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES)) + { + name_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUES); + } + else if (JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES)) + { + name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENTRIES); + } + else + { + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (name_id)); + name_p = ecma_op_get_global_symbol (name_id); + } + } + else + { + name_p = ecma_get_magic_string (name_id); + } + + const char *prefix_p = NULL; + lit_utf8_size_t prefix_size = 0; + + if (*bitset_p & (ECMA_BUILTIN_ROUTINE_GETTER | ECMA_BUILTIN_ROUTINE_SETTER)) + { + prefix_size = 4; + prefix_p = (*bitset_p & ECMA_BUILTIN_ROUTINE_GETTER) ? "get " : "set "; + } + + name_prop_value_p->value = ecma_op_function_form_name (name_p, (char*)prefix_p, prefix_size); + + if (JERRY_UNLIKELY (name_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + ecma_deref_ecma_string (name_p); + } + + return name_prop_p; + } + + return NULL; +} /* ecma_builtin_routine_try_to_instantiate_property */ + +/** + * If the property's name is one of built-in properties of the object + * that is not instantiated yet, instantiate the property and + * return pointer to the instantiated property. + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + lit_magic_string_id_t magic_string_id = ecma_get_string_magic (property_name_p); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p)) && property_name_p->u.hash & ECMA_SYMBOL_FLAG_GLOBAL) + { + magic_string_id = (lit_magic_string_id_t) ((int) property_name_p->u.hash >> (int) ECMA_SYMBOL_FLAGS_SHIFT); + } + + if (magic_string_id == LIT_MAGIC_STRING__COUNT) + { + return NULL; + } + + ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY + || (object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION && !ecma_builtin_function_is_routine (object_p))); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + } + + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; + + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + while (curr_property_p->magic_string_id != magic_string_id) + { + if (curr_property_p->magic_string_id == LIT_MAGIC_STRING__COUNT) + { + return NULL; + } + curr_property_p++; + } + + uint32_t index = (uint32_t) (curr_property_p - property_list_p); + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + (index >> 3); + +#if JERRY_BUILTIN_REALMS + if (index >= 8 * sizeof (uint8_t)) + { + bitset_p += sizeof (ecma_value_t); + } +#endif /* JERRY_BUILTIN_REALMS */ + + uint8_t bit_for_index = (uint8_t) (1u << (index & 0x7)); + + if (*bitset_p & bit_for_index) + { + /* This property was instantiated before. */ + return NULL; + } + + ecma_value_t value = ECMA_VALUE_EMPTY; + bool is_accessor = false; + ecma_object_t *getter_p = NULL; + ecma_object_t *setter_p = NULL; + + switch (curr_property_p->type) + { + case ECMA_BUILTIN_PROPERTY_SIMPLE: + { + value = curr_property_p->value; + +#if JERRY_BUILTIN_GLOBAL_THIS + if (value == ECMA_VALUE_GLOBAL_THIS) + { + /* Only the global object has globalThis property. */ + JERRY_ASSERT (ecma_builtin_is_global (object_p)); + ecma_ref_object (object_p); + value = ecma_make_object_value (object_p); + } +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ + break; + } + case ECMA_BUILTIN_PROPERTY_NUMBER: + { + ecma_number_t num = 0.0; + + if (curr_property_p->value < ECMA_BUILTIN_NUMBER_MAX) + { + num = curr_property_p->value; + } + else if (curr_property_p->value < ECMA_BUILTIN_NUMBER_NAN) + { + static const ecma_number_t builtin_number_list[] = { + ECMA_NUMBER_MAX_VALUE, + ECMA_NUMBER_MIN_VALUE, + ECMA_NUMBER_EPSILON, + ECMA_NUMBER_MAX_SAFE_INTEGER, + ECMA_NUMBER_MIN_SAFE_INTEGER, + ECMA_NUMBER_E, + ECMA_NUMBER_PI, + ECMA_NUMBER_LN10, + ECMA_NUMBER_LN2, + ECMA_NUMBER_LOG2E, + ECMA_NUMBER_LOG10E, + ECMA_NUMBER_SQRT2, + ECMA_NUMBER_SQRT_1_2, + }; + + num = builtin_number_list[curr_property_p->value - ECMA_BUILTIN_NUMBER_MAX]; + } + else + { + switch (curr_property_p->value) + { + case ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY: + { + num = ecma_number_make_infinity (false); + break; + } + case ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY: + { + num = ecma_number_make_infinity (true); + break; + } + default: + { + JERRY_ASSERT (curr_property_p->value == ECMA_BUILTIN_NUMBER_NAN); + + num = ecma_number_make_nan (); + break; + } + } + } + + value = ecma_make_number_value (num); + break; + } + case ECMA_BUILTIN_PROPERTY_STRING: + { + value = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->value); + break; + } + case ECMA_BUILTIN_PROPERTY_SYMBOL: + { + lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->value; + + value = ecma_make_symbol_value (ecma_op_get_global_symbol (symbol_id)); + break; + } + case ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY: + { + ecma_object_t *intrinsic_object_p = ecma_builtin_get_from_builtin (object_p, ECMA_BUILTIN_ID_INTRINSIC_OBJECT); + value = ecma_op_object_get_by_magic_id (intrinsic_object_p, (lit_magic_string_id_t) curr_property_p->value); + break; + } + case ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION: + { + is_accessor = true; + uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value); + uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value); + getter_p = ecma_builtin_get_from_builtin (object_p, (ecma_builtin_id_t) getter_id); + setter_p = ecma_builtin_get_from_builtin (object_p, (ecma_builtin_id_t) setter_id); + ecma_ref_object (getter_p); + ecma_ref_object (setter_p); + break; + } + case ECMA_BUILTIN_PROPERTY_OBJECT: + { + ecma_object_t *builtin_object_p; + builtin_object_p = ecma_builtin_get_from_builtin (object_p, (ecma_builtin_id_t) curr_property_p->value); + ecma_ref_object (builtin_object_p); + value = ecma_make_object_value (builtin_object_p); + break; + } + case ECMA_BUILTIN_PROPERTY_ROUTINE: + { + ecma_object_t *func_obj_p; + func_obj_p = ecma_builtin_make_function_object_for_routine (object_p, + ECMA_GET_ROUTINE_ID (curr_property_p->value), + index, + ECMA_BUILTIN_ROUTINE_NO_OPTS); + value = ecma_make_object_value (func_obj_p); + break; + } + case ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE: + { + is_accessor = true; + uint8_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value); + uint8_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value); + getter_p = ecma_builtin_make_function_object_for_getter_accessor (object_p, getter_id, index); + setter_p = ecma_builtin_make_function_object_for_setter_accessor (object_p, setter_id, index); + break; + } + default: + { + JERRY_ASSERT (curr_property_p->type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY); + + is_accessor = true; + uint8_t getter_id = (uint8_t) curr_property_p->value; + getter_p = ecma_builtin_make_function_object_for_getter_accessor (object_p, getter_id, index); + break; + } + } + + ecma_property_t *prop_p; + + JERRY_ASSERT (curr_property_p->attributes & ECMA_PROPERTY_FLAG_BUILT_IN); + + if (is_accessor) + { + ecma_create_named_accessor_property (object_p, + property_name_p, + getter_p, + setter_p, + curr_property_p->attributes, + &prop_p); + + if (setter_p) + { + ecma_deref_object (setter_p); + } + if (getter_p) + { + ecma_deref_object (getter_p); + } + } + else + { + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, curr_property_p->attributes, &prop_p); + prop_value_p->value = value; + + /* Reference count of objects must be decreased. */ + ecma_deref_if_object (value); + } + + return prop_p; +} /* ecma_builtin_try_to_instantiate_property */ + +/** + * Delete configurable properties of native handlers. + */ +static void +ecma_builtin_native_handler_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED)); + + extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED; + return; + } + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED)); + + extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED; +} /* ecma_builtin_native_handler_delete_built_in_property */ + +/** + * Delete configurable properties of built-in routines. + */ +void +ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + && ecma_builtin_function_is_routine (object_p)); + + ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (extended_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + ecma_builtin_native_handler_delete_built_in_property (object_p, property_name_p); + return; + } + + uint8_t *bitset_p = &extended_obj_p->u.built_in.u2.routine_flags; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED)); + + *bitset_p |= ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED; + return; + } + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED)); + + *bitset_p |= ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED; +} /* ecma_builtin_routine_delete_built_in_property */ + +/** + * Delete configurable properties of built-ins. + */ +void +ecma_builtin_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + lit_magic_string_id_t magic_string_id = ecma_get_string_magic (property_name_p); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + if (property_name_p->u.hash & ECMA_SYMBOL_FLAG_GLOBAL) + { + magic_string_id = (lit_magic_string_id_t ) ((int) property_name_p->u.hash >> ECMA_SYMBOL_FLAGS_SHIFT); + } + } + + ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY + || (object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION && !ecma_builtin_function_is_routine (object_p))); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + } + + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; + + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + while (curr_property_p->magic_string_id != magic_string_id) + { + JERRY_ASSERT (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT); + curr_property_p++; + } + + uint32_t index = (uint32_t) (curr_property_p - property_list_p); + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + (index >> 3); + +#if JERRY_BUILTIN_REALMS + if (index >= 8 * sizeof (uint8_t)) + { + bitset_p += sizeof (ecma_value_t); + } +#endif /* JERRY_BUILTIN_REALMS */ + + uint8_t bit_for_index = (uint8_t) (1u << (index & 0x7)); + JERRY_ASSERT (!(*bitset_p & bit_for_index)); + + *bitset_p |= bit_for_index; +} /* ecma_builtin_delete_built_in_property */ + +/** + * List names of an Built-in native handler object's lazy instantiated properties, + * adding them to corresponding string collections + */ +static void +ecma_builtin_native_handler_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p) /**< prop counter */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED) == 0) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_NAME)); + prop_counter_p->string_named_props++; + } + + if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED) == 0) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } +} /* ecma_builtin_native_handler_list_lazy_property_names */ + +/** + * List names of a built-in function's lazy instantiated properties + * + * See also: + * ecma_builtin_routine_try_to_instantiate_property + */ +void +ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + JERRY_ASSERT (ecma_builtin_function_is_routine (object_p)); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (JERRY_UNLIKELY (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + ecma_builtin_native_handler_list_lazy_property_names (object_p, prop_names_p, prop_counter_p); + return; + } + + if (!(ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED)) + { + /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + if (!(ext_func_p->u.built_in.u2.routine_flags & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED)) + { + /* Unintialized 'name' property is non-enumerable (ECMA-262 v6, 19.2.4.2) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_NAME)); + prop_counter_p->string_named_props++; + } +} /* ecma_builtin_routine_list_lazy_property_names */ + +/** + * List names of a built-in object's lazy instantiated properties + * + * See also: + * ecma_builtin_try_to_instantiate_property + */ +void +ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || !ecma_builtin_function_is_routine (object_p)); + + ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) + { + built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + } + + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; + + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + +#if JERRY_BUILTIN_REALMS + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t); +#else /* !JERRY_BUILTIN_REALMS */ + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1; +#endif /* JERRY_BUILTIN_REALMS */ + + uint8_t *symbol_bitset_p = bitset_p; + bool has_symbol = true; + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; + uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0]; + uint32_t index = 0; + + has_symbol = false; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) + { + if (index == 8) + { + bitset = *bitset_p++; + index = 0; + } + + uint32_t bit_for_index = (uint32_t) 1u << index; + + if (!(bitset & bit_for_index)) + { + if (JERRY_LIKELY (curr_property_p->magic_string_id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id); + ecma_collection_push_back (prop_names_p, name); + prop_counter_p->string_named_props++; + } + else + { + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (curr_property_p->magic_string_id)); + has_symbol = true; + } + } + + curr_property_p++; + index++; + } + } + + if (has_symbol && !(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS)) + { + const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; + uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0]; + uint32_t index = 0; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) + { + if (index == 8) + { + bitset = *symbol_bitset_p++; + index = 0; + } + + uint32_t bit_for_index = (uint32_t) 1u << index; + + if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT && !(bitset & bit_for_index)) + { + ecma_string_t *name_p = ecma_op_get_global_symbol ((lit_magic_string_id_t ) curr_property_p->magic_string_id); + ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (name_p)); + prop_counter_p->symbol_named_props++; + } + + curr_property_p++; + index++; + } + } +} /* ecma_builtin_list_lazy_property_names */ + +/** + * Dispatcher of built-in routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_dispatch_routine (ecma_extended_object_t *func_obj_p, /**< builtin object */ + ecma_value_t this_arg_value, /**< 'this' argument value */ + const ecma_value_t *arguments_list_p, /**< list of arguments passed to routine */ + uint32_t arguments_list_len) /**< length of arguments' list */ +{ + JERRY_ASSERT (ecma_builtin_function_is_routine ((ecma_object_t *) func_obj_p)); + + ecma_value_t padded_arguments_list_p[3] = { ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED }; + + if (arguments_list_len <= 2) + { + switch (arguments_list_len) + { + case 2: + { + padded_arguments_list_p[1] = arguments_list_p[1]; + /* FALLTHRU */ + } + case 1: + { + padded_arguments_list_p[0] = arguments_list_p[0]; + break; + } + default: + { + JERRY_ASSERT (arguments_list_len == 0); + } + } + + arguments_list_p = padded_arguments_list_p; + } + + return ecma_builtin_routines[func_obj_p->u.built_in.id](func_obj_p->u.built_in.routine_id, + this_arg_value, + arguments_list_p, + arguments_list_len); +} /* ecma_builtin_dispatch_routine */ + +/** + * Handle calling [[Call]] of built-in object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ + ecma_value_t this_arg_value, /**< 'this' argument value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (ecma_builtin_function_is_routine (obj_p)) + { + if (JERRY_UNLIKELY (ext_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + ecma_builtin_handler_t handler = ecma_builtin_handler_get ((ecma_native_handler_id_t ) ext_obj_p->u.built_in.routine_id); + return handler (obj_p, arguments_list_p, arguments_list_len); + } + + return ecma_builtin_dispatch_routine (ext_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + } + + ecma_builtin_id_t builtin_object_id = (ecma_builtin_id_t) ext_obj_p->u.built_in.id; + JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t)); + return ecma_builtin_call_functions[builtin_object_id](arguments_list_p, arguments_list_len); +} /* ecma_builtin_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + if (ecma_builtin_function_is_routine (obj_p)) + { + return ecma_raise_type_error (ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR); + } + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ecma_builtin_id_t builtin_object_id = (ecma_builtin_id_t) ext_obj_p->u.built_in.id; + JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t)); + + return ecma_builtin_construct_functions[builtin_object_id](arguments_list_p, arguments_list_len); +} /* ecma_builtin_dispatch_construct */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.h new file mode 100644 index 00000000..82761cdc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.h @@ -0,0 +1,136 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BUILTINS_H +#define ECMA_BUILTINS_H + +#include "ecma-globals.h" + +/** + * A built-in object's identifier + */ +typedef enum +{ +/** @cond doxygen_suppress */ +#define BUILTIN(a, b, c, d, e) +#define BUILTIN_ROUTINE(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) builtin_id, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE +#define BUILTIN_ROUTINE(a, b, c, d, e) +#define BUILTIN(builtin_id, object_type, object_prototype_builtin_id, is_extensible, lowercase_name) builtin_id, +#include "ecma-builtins.inc.h" +#undef BUILTIN +#undef BUILTIN_ROUTINE + /** @endcond */ + ECMA_BUILTIN_ID__COUNT /**< number of built-in objects */ +} ecma_builtin_id_t; + +/** + * Special id for handlers (handlers are not regular built-ins, but + * they use the same ecma_built_in_props_t structure as other built-ins) + */ +#define ECMA_BUILTIN_ID_HANDLER ECMA_BUILTIN_ID__COUNT + +/** + * Number of global symbols + */ +#define ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT (LIT_GLOBAL_SYMBOL__LAST - LIT_GLOBAL_SYMBOL__FIRST + 1) + +/** + * Construct a routine value + */ +#define ECMA_ROUTINE_VALUE(id, length) (((id) << 4) | length) + +/** + * Get routine length + */ +#define ECMA_GET_ROUTINE_LENGTH(value) ((uint8_t) ((value) &0xf)) + +/** + * Get routine ID + */ +#define ECMA_GET_ROUTINE_ID(value) ((uint8_t) ((value) >> 4)) + +/** + * Construct a fully accessor value + */ +#define ECMA_ACCESSOR_READ_WRITE(getter, setter) (((getter) << 8) | (setter)) + +/** + * Get accessor setter ID + */ +#define ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID(value) ((uint8_t) ((value) &0xff)) + +/** + * Get accessor getter ID + */ +#define ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID(value) ((uint8_t) ((value) >> 8)) + +/** + * Number ob built-in objects excluding global object + */ +#define ECMA_BUILTIN_OBJECTS_COUNT (ECMA_BUILTIN_ID__COUNT - 1) + +/** + * Description of built-in global ECMA-object. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + uint32_t extra_instantiated_bitset[1]; /**< extra bit set for instantiated properties */ +#if JERRY_BUILTIN_REALMS + uint32_t extra_realms_bitset; /**< extra bit set for instantiated properties when realms is enabled */ + ecma_value_t this_binding; /**< 'this' binding of this global object */ +#endif /* JERRY_BUILTIN_REALMS */ + jmem_cpointer_t global_env_cp; /**< global lexical environment */ + jmem_cpointer_t global_scope_cp; /**< global lexical scope */ + jmem_cpointer_t builtin_objects[ECMA_BUILTIN_OBJECTS_COUNT]; /**< pointer to instances of built-in objects */ +} ecma_global_object_t; + +/* ecma-builtins.c */ + +ecma_global_object_t *ecma_builtin_create_global_object (void); + +ecma_value_t ecma_builtin_dispatch_call (ecma_object_t *obj_p, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_value_t ecma_builtin_dispatch_construct (ecma_object_t *obj_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_property_t *ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); +ecma_property_t *ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +void ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +void ecma_builtin_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +void ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +bool ecma_builtin_is_global (ecma_object_t *object_p); +ecma_object_t *ecma_builtin_get (ecma_builtin_id_t builtin_id); +ecma_object_t *ecma_builtin_get_global (void); +bool ecma_builtin_function_is_routine (ecma_object_t *func_obj_p); + +#if JERRY_BUILTIN_REALMS +ecma_object_t *ecma_builtin_get_from_realm (ecma_global_object_t *global_object_p, ecma_builtin_id_t builtin_id); +#endif /* JERRY_BUILTIN_REALMS */ + +#endif /* !ECMA_BUILTINS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h new file mode 100644 index 00000000..9cbfae26 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h @@ -0,0 +1,747 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Description of built-in objects + in format (ECMA_BUILTIN_ID_id, object_type, prototype_id, is_extensible, is_static, underscored_id) */ + +/* The Object.prototype object (15.2.4) */ +BUILTIN (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID__COUNT /* no prototype */, + true, + object_prototype) + +/* The Object object (15.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_OBJECT, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + object) + +#if JERRY_BUILTIN_ARRAY +/* The Array.prototype object (15.4.4) */ +BUILTIN (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_ARRAY, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + array_prototype) + +/* The Array object (15.4.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + array) +#endif /* JERRY_BUILTIN_ARRAY */ + +#if JERRY_BUILTIN_DATE +/* The Date.prototype object (20.3.4) */ +BUILTIN (ECMA_BUILTIN_ID_DATE_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + date_prototype) +#endif /* JERRY_BUILTIN_DATE */ + +#if JERRY_BUILTIN_REGEXP +/* The RegExp.prototype object (21.2.5) */ +BUILTIN (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + regexp_prototype) +#endif /* JERRY_BUILTIN_REGEXP */ + +#if JERRY_BUILTIN_STRING +/* The String.prototype object (15.5.4) */ +BUILTIN (ECMA_BUILTIN_ID_STRING_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_CLASS, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + string_prototype) + +/* The String object (15.5.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_STRING, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + string) +#endif /* JERRY_BUILTIN_STRING */ + +#if JERRY_BUILTIN_BOOLEAN +/* The Boolean.prototype object (15.6.4) */ +BUILTIN (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_CLASS, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + boolean_prototype) + +/* The Boolean object (15.6.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BOOLEAN, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + boolean) +#endif /* JERRY_BUILTIN_BOOLEAN */ + +#if JERRY_BUILTIN_NUMBER +/* The Number.prototype object (15.7.4) */ +BUILTIN (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_CLASS, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + number_prototype) + +/* The Number object (15.7.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_NUMBER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + number) +#endif /* JERRY_BUILTIN_NUMBER */ + +/* The Function.prototype object (15.3.4) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + function_prototype) + +/* The Function object (15.3.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + function) + +#if JERRY_BUILTIN_MATH +/* The Math object (15.8) */ +BUILTIN (ECMA_BUILTIN_ID_MATH, ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, math) +#endif /* JERRY_BUILTIN_MATH */ + +#if JERRY_BUILTIN_REFLECT + +/* The Reflect object (26.1) */ +BUILTIN (ECMA_BUILTIN_ID_REFLECT, ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, reflect) +#endif /* JERRY_BUILTIN_REFLECT */ + +#if JERRY_BUILTIN_ATOMICS +/* The Atomics object (24.4) */ +BUILTIN (ECMA_BUILTIN_ID_ATOMICS, ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, true, atomics) +#endif /* JERRY_BUILTIN_ATOMICS */ + +#if JERRY_BUILTIN_DATE +/* The Date object (15.9.3) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_DATE, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + date) +#endif /* JERRY_BUILTIN_DATE */ + +#if JERRY_BUILTIN_REGEXP +/* The RegExp object (15.10) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_REGEXP, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + regexp) +#endif /* JERRY_BUILTIN_REGEXP */ + +#define ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID ECMA_BUILTIN_ID_ERROR + +/* The Error object (15.11.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + error) + +/* The Error.prototype object (15.11.4) */ +BUILTIN (ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + error_prototype) + +#if JERRY_BUILTIN_ERRORS +/* The EvalError.prototype object (15.11.6.1) */ +BUILTIN (ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + eval_error_prototype) + +/* The EvalError object (15.11.6.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_EVAL_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + eval_error) + +/* The RangeError.prototype object (15.11.6.2) */ +BUILTIN (ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + range_error_prototype) + +/* The RangeError object (15.11.6.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_RANGE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + range_error) + +/* The ReferenceError.prototype object (15.11.6.3) */ +BUILTIN (ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + reference_error_prototype) + +/* The ReferenceError object (15.11.6.3) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_REFERENCE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + reference_error) + +/* The SyntaxError.prototype object (15.11.6.4) */ +BUILTIN (ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + syntax_error_prototype) + +/* The SyntaxError object (15.11.6.4) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SYNTAX_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + syntax_error) + +/* The TypeError.prototype object (15.11.6.5) */ +BUILTIN (ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + type_error_prototype) + +/* The TypeError object (15.11.6.5) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_TYPE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + type_error) + +/* The AggregateError.prototype object (15.11.6.5) */ +BUILTIN (ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + aggregate_error_prototype) + +/* The AggregateError object (15.11.6.5) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_AGGREGATE_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + aggregate_error) + +/* The URIError.prototype object (15.11.6.6) */ +BUILTIN (ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ERROR_PROTOTYPE, + true, + uri_error_prototype) + +/* The URIError object (15.11.6.6) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_URI_ERROR, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_NATIVE_ERROR_PROTOTYPE_ID, + true, + uri_error) +#endif /* JERRY_BUILTIN_ERRORS */ + +/**< The [[ThrowTypeError]] object (13.2.3) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + false, + type_error_thrower) + +#if JERRY_BUILTIN_TYPEDARRAY + +/* The ArrayBuffer.prototype object (ES2015 24.1.4) */ +BUILTIN (ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + arraybuffer_prototype) + +/* The ArrayBuffer object (ES2015 24.1.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ARRAYBUFFER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + arraybuffer) + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/* The SharedArrayBuffer.prototype object (ES2015 24.2.4) */ +BUILTIN (ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + shared_arraybuffer_prototype) + +/* The SharedArrayBuffer object (ES2015 24.2.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + shared_arraybuffer) +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +/* The %TypedArrayPrototype% object (ES2015 24.2.3) */ +BUILTIN (ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + typedarray_prototype) + +/* The %TypedArray% intrinsic object (ES2015 22.2.1) + Note: The routines must be in this order. */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_TYPEDARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + typedarray) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_INT8ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + int8array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT8ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint8array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint8clampedarray) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_INT16ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + int16array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT16ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint16array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_INT32ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + int32array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_UINT32ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + uint32array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FLOAT32ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + float32array) + +#if JERRY_NUMBER_TYPE_FLOAT64 +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_FLOAT64ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + float64array) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BIGINT64ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + bigint64array) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BIGUINT64ARRAY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_TYPEDARRAY, + true, + biguint64array) +#endif /* JERRY_BUILTIN_BIGINT */ + +BUILTIN (ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + int8array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT8ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint8array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint8clampedarray_prototype) + +BUILTIN (ECMA_BUILTIN_ID_INT16ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + int16array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT16ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint16array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_INT32ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + int32array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_UINT32ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + uint32array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_FLOAT32ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + float32array_prototype) + +#if JERRY_NUMBER_TYPE_FLOAT64 +BUILTIN (ECMA_BUILTIN_ID_FLOAT64ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + float64array_prototype) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +BUILTIN (ECMA_BUILTIN_ID_BIGINT64ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + bigint64array_prototype) + +BUILTIN (ECMA_BUILTIN_ID_BIGUINT64ARRAY_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, + true, + biguint64array_prototype) +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +BUILTIN (ECMA_BUILTIN_ID_PROMISE_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + promise_prototype) + +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_PROMISE, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + promise) + +#if JERRY_BUILTIN_CONTAINER + +/* The Map prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_MAP_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + map_prototype) + +/* The Map routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_MAP, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, map) + +/* The Set prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_SET_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + set_prototype) + +/* The Set routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SET, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, true, set) + +/* The WeakMap prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + weakmap_prototype) + +/* The WeakMap routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_WEAKMAP, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + weakmap) + +/* The WeakSet prototype object (23.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + weakset_prototype) + +/* The WeakSet routine (ECMA-262 v6, 23.1.1.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_WEAKSET, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + weakset) + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#if JERRY_BUILTIN_WEAKREF + +/* The WeakRef prototype object */ +BUILTIN (ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + weakref_prototype) + +/* The WeakRef routine */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_WEAKREF, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + weakref) + +#endif /* JERRY_BUILTIN_WEAKREF */ + +#if (JERRY_BUILTIN_PROXY) +/* The Proxy routine (ECMA-262 v6, 26.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_PROXY, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + proxy) +#endif /* JERRY_BUILTIN_PROXY */ + +/* Intrinsic hidden builtin object */ +BUILTIN (ECMA_BUILTIN_ID_INTRINSIC_OBJECT, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID__COUNT /* no prototype */, + true, + intrinsic) + +/* The Array.prototype[@@unscopables] object */ +BUILTIN (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID__COUNT /* no prototype */, + true, + array_prototype_unscopables) + +/* The Symbol prototype object (ECMA-262 v6, 19.4.2.7) */ +BUILTIN (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + symbol_prototype) + +/* The Symbol routine (ECMA-262 v6, 19.4.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SYMBOL, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + symbol) + +/* The %AsyncFunction% object (ECMA-262 v11, 25.7.2) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ASYNC_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION, + true, + async_function) + +/* The %AsyncFunctionPrototype% object (ECMA-262 v11, 25.7.3) */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + async_function_prototype) + +/* The %IteratorPrototype% object (ECMA-262 v6, 25.1.2) */ +BUILTIN (ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + iterator_prototype) + +/* The %ArrayIteratorPrototype% object (ECMA-262 v6, 22.1.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + array_iterator_prototype) + +/* The %StringIteratorPrototype% object (ECMA-262 v6, 22.1.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + string_iterator_prototype) + +/* The %RegExpStringIteratorPrototype% object (ECMA-262 v11, 21.2.7.1) */ +BUILTIN (ECMA_BUILTIN_ID_REGEXP_STRING_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + regexp_string_iterator_prototype) + +/* The %AsyncIteratorPrototype% object (ECMA-262 v10, 25.1.3) */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + async_iterator_prototype) + +/* The %AsyncFromSyncIteratorPrototype% object (ECMA-262 v11, 25.1.4.2) */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ASYNC_ITERATOR_PROTOTYPE, + true, + async_from_sync_iterator_prototype) + +/* The %(GeneratorFunction)% object */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_GENERATOR_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION, + true, + generator_function) + +/* The %(Generator)% object */ +BUILTIN (ECMA_BUILTIN_ID_GENERATOR, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + generator) + +/* The %(Generator).prototype% object */ +BUILTIN (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + generator_prototype) + +/* The %(AsyncGeneratorFunction)% object */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ASYNC_GENERATOR_FUNCTION, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION, + true, + async_generator_function) + +/* The %(AsyncGenerator)% object */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_GENERATOR, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + async_generator) + +/* The %(AsyncGenerator).prototype% object */ +BUILTIN (ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ASYNC_ITERATOR_PROTOTYPE, + true, + async_generator_prototype) + +#if JERRY_BUILTIN_CONTAINER +/* The %SetIteratorPrototype% object (ECMA-262 v6, 23.2.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + set_iterator_prototype) + +/* The %MapIteratorPrototype% object (ECMA-262 v6, 23.1.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + map_iterator_prototype) +#endif /* JERRY_BUILTIN_CONTAINER */ + +#if JERRY_BUILTIN_BIGINT +/* The %BigInt.prototype% object */ +BUILTIN (ECMA_BUILTIN_ID_BIGINT_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + bigint_prototype) + +/* The %BigInt% object */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BIGINT, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + bigint) +#endif /* JERRY_BUILTIN_BIGINT */ + +#if JERRY_BUILTIN_DATAVIEW +/* The DataView prototype object (ECMA-262 v6, 24.2.3.1) */ +BUILTIN (ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + dataview_prototype) + +/* The DataView routine (ECMA-262 v6, 24.2.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_DATAVIEW, + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + dataview) +#endif /* JERRY_BUILTIN_DATAVIEW */ + +/* The Global object (15.1) */ +BUILTIN (ECMA_BUILTIN_ID_GLOBAL, + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, /* Implementation-dependent */ + true, + global) + +#undef BUILTIN diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/meson.build new file mode 100644 index 00000000..89a95c0e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/meson.build @@ -0,0 +1,182 @@ +subdir('typedarray') + +source_file = [ + 'ecma-builtin-aggregateerror-prototype.inc.h', + 'ecma-builtin-aggregateerror.inc.h', + 'ecma-builtin-array-iterator-prototype.inc.h', + 'ecma-builtin-array-prototype-unscopables.inc.h', + 'ecma-builtin-array-prototype.inc.h', + 'ecma-builtin-array.inc.h', + 'ecma-builtin-arraybuffer-prototype.inc.h', + 'ecma-builtin-arraybuffer.inc.h', + 'ecma-builtin-async-from-sync-iterator-prototype.inc.h', + 'ecma-builtin-async-function-prototype.inc.h', + 'ecma-builtin-async-function.inc.h', + 'ecma-builtin-async-generator-function.inc.h', + 'ecma-builtin-async-generator-prototype.inc.h', + 'ecma-builtin-async-generator.inc.h', + 'ecma-builtin-async-iterator-prototype.inc.h', + 'ecma-builtin-atomics.inc.h', + 'ecma-builtin-bigint-prototype.inc.h', + 'ecma-builtin-bigint.inc.h', + 'ecma-builtin-boolean-prototype.inc.h', + 'ecma-builtin-boolean.inc.h', + 'ecma-builtin-dataview-prototype.inc.h', + 'ecma-builtin-dataview.inc.h', + 'ecma-builtin-date-prototype.inc.h', + 'ecma-builtin-date.inc.h', + 'ecma-builtin-error-prototype.inc.h', + 'ecma-builtin-error.inc.h', + 'ecma-builtin-evalerror-prototype.inc.h', + 'ecma-builtin-evalerror.inc.h', + 'ecma-builtin-function-prototype.h', + 'ecma-builtin-function-prototype.inc.h', + 'ecma-builtin-function.inc.h', + 'ecma-builtin-generator-function.inc.h', + 'ecma-builtin-generator-prototype.inc.h', + 'ecma-builtin-generator.inc.h', + 'ecma-builtin-global.inc.h', + 'ecma-builtin-handlers.h', + 'ecma-builtin-handlers.inc.h', + 'ecma-builtin-helpers-macro-defines.inc.h', + 'ecma-builtin-helpers-macro-undefs.inc.h', + 'ecma-builtin-helpers.h', + 'ecma-builtin-internal-routines-template.inc.h', + 'ecma-builtin-intrinsic.inc.h', + 'ecma-builtin-iterator-prototype.inc.h', + 'ecma-builtin-map-iterator-prototype.inc.h', + 'ecma-builtin-map-prototype.inc.h', + 'ecma-builtin-map.inc.h', + 'ecma-builtin-math.inc.h', + 'ecma-builtin-number-prototype.inc.h', + 'ecma-builtin-number.inc.h', + 'ecma-builtin-object-prototype.inc.h', + 'ecma-builtin-object.h', + 'ecma-builtin-object.inc.h', + 'ecma-builtin-promise-prototype.inc.h', + 'ecma-builtin-promise.inc.h', + 'ecma-builtin-proxy.inc.h', + 'ecma-builtin-rangeerror-prototype.inc.h', + 'ecma-builtin-rangeerror.inc.h', + 'ecma-builtin-referenceerror-prototype.inc.h', + 'ecma-builtin-referenceerror.inc.h', + 'ecma-builtin-reflect.inc.h', + 'ecma-builtin-regexp-prototype.inc.h', + 'ecma-builtin-regexp-string-iterator-prototype.inc.h', + 'ecma-builtin-regexp.inc.h', + 'ecma-builtin-set-iterator-prototype.inc.h', + 'ecma-builtin-set-prototype.inc.h', + 'ecma-builtin-set.inc.h', + 'ecma-builtin-shared-arraybuffer-prototype.inc.h', + 'ecma-builtin-shared-arraybuffer.inc.h', + 'ecma-builtin-string-iterator-prototype.inc.h', + 'ecma-builtin-string-prototype.inc.h', + 'ecma-builtin-string.inc.h', + 'ecma-builtin-symbol-prototype.inc.h', + 'ecma-builtin-symbol.inc.h', + 'ecma-builtin-syntaxerror-prototype.inc.h', + 'ecma-builtin-syntaxerror.inc.h', + 'ecma-builtin-type-error-thrower.inc.h', + 'ecma-builtin-typeerror-prototype.inc.h', + 'ecma-builtin-typeerror.inc.h', + 'ecma-builtin-urierror-prototype.inc.h', + 'ecma-builtin-urierror.inc.h', + 'ecma-builtin-weakmap-prototype.inc.h', + 'ecma-builtin-weakmap.inc.h', + 'ecma-builtin-weakref-prototype.inc.h', + 'ecma-builtin-weakref.inc.h', + 'ecma-builtin-weakset-prototype.inc.h', + 'ecma-builtin-weakset.inc.h', + 'ecma-builtins-internal.h', + 'ecma-builtins.h', + 'ecma-builtins.inc.h', + 'ecma-builtin-aggregateerror-prototype.cpp', + 'ecma-builtin-aggregateerror.cpp', + 'ecma-builtin-array-iterator-prototype.cpp', + 'ecma-builtin-array-prototype-unscopables.cpp', + 'ecma-builtin-array-prototype.cpp', + 'ecma-builtin-array.cpp', + 'ecma-builtin-arraybuffer-prototype.cpp', + 'ecma-builtin-arraybuffer.cpp', + 'ecma-builtin-async-from-sync-iterator-prototype.cpp', + 'ecma-builtin-async-function-prototype.cpp', + 'ecma-builtin-async-function.cpp', + 'ecma-builtin-async-generator-function.cpp', + 'ecma-builtin-async-generator-prototype.cpp', + 'ecma-builtin-async-generator.cpp', + 'ecma-builtin-async-iterator-prototype.cpp', + 'ecma-builtin-atomics.cpp', + 'ecma-builtin-bigint-prototype.cpp', + 'ecma-builtin-bigint.cpp', + 'ecma-builtin-boolean-prototype.cpp', + 'ecma-builtin-boolean.cpp', + 'ecma-builtin-dataview-prototype.cpp', + 'ecma-builtin-dataview.cpp', + 'ecma-builtin-date-prototype.cpp', + 'ecma-builtin-date.cpp', + 'ecma-builtin-error-prototype.cpp', + 'ecma-builtin-error.cpp', + 'ecma-builtin-evalerror-prototype.cpp', + 'ecma-builtin-evalerror.cpp', + 'ecma-builtin-function-prototype.cpp', + 'ecma-builtin-function.cpp', + 'ecma-builtin-generator-function.cpp', + 'ecma-builtin-generator-prototype.cpp', + 'ecma-builtin-generator.cpp', + 'ecma-builtin-global.cpp', + 'ecma-builtin-handlers.cpp', + 'ecma-builtin-helpers-date.cpp', + 'ecma-builtin-helpers-error.cpp', + 'ecma-builtin-helpers-sort.cpp', + 'ecma-builtin-helpers.cpp', + 'ecma-builtin-intrinsic.cpp', + 'ecma-builtin-iterator-prototype.cpp', + 'ecma-builtin-map-iterator-prototype.cpp', + 'ecma-builtin-map-prototype.cpp', + 'ecma-builtin-map.cpp', + 'ecma-builtin-math.cpp', + 'ecma-builtin-number-prototype.cpp', + 'ecma-builtin-number.cpp', + 'ecma-builtin-object-prototype.cpp', + 'ecma-builtin-object.cpp', + 'ecma-builtin-promise-prototype.cpp', + 'ecma-builtin-promise.cpp', + 'ecma-builtin-proxy.cpp', + 'ecma-builtin-rangeerror-prototype.cpp', + 'ecma-builtin-rangeerror.cpp', + 'ecma-builtin-referenceerror-prototype.cpp', + 'ecma-builtin-referenceerror.cpp', + 'ecma-builtin-reflect.cpp', + 'ecma-builtin-regexp-prototype.cpp', + 'ecma-builtin-regexp-string-iterator-prototype.cpp', + 'ecma-builtin-regexp.cpp', + 'ecma-builtin-set-iterator-prototype.cpp', + 'ecma-builtin-set-prototype.cpp', + 'ecma-builtin-set.cpp', + 'ecma-builtin-shared-arraybuffer-prototype.cpp', + 'ecma-builtin-shared-arraybuffer.cpp', + 'ecma-builtin-string-iterator-prototype.cpp', + 'ecma-builtin-string-prototype.cpp', + 'ecma-builtin-string.cpp', + 'ecma-builtin-symbol-prototype.cpp', + 'ecma-builtin-symbol.cpp', + 'ecma-builtin-syntaxerror-prototype.cpp', + 'ecma-builtin-syntaxerror.cpp', + 'ecma-builtin-type-error-thrower.cpp', + 'ecma-builtin-typeerror-prototype.cpp', + 'ecma-builtin-typeerror.cpp', + 'ecma-builtin-urierror-prototype.cpp', + 'ecma-builtin-urierror.cpp', + 'ecma-builtin-weakmap-prototype.cpp', + 'ecma-builtin-weakmap.cpp', + 'ecma-builtin-weakref-prototype.cpp', + 'ecma-builtin-weakref.cpp', + 'ecma-builtin-weakset-prototype.cpp', + 'ecma-builtin-weakset.cpp', + 'ecma-builtins.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.cpp new file mode 100644 index 00000000..3b33e033 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.cpp @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint64array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint64array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint64arrayprototype ECMA BigInt64Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.inc.h new file mode 100644 index 00000000..5e1087bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt64Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGINT64ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.cpp new file mode 100644 index 00000000..ae7fc964 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint64array.inc.h" +#define BUILTIN_UNDERSCORED_ID bigint64array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup bigint64array ECMA BigInt64Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of BigInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint64array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_BIGINT64_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_bigint64array_dispatch_call */ + +/** + * Handle calling [[Construct]] of BigInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_bigint64array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_BIGINT64_ARRAY); +} /* ecma_builtin_bigint64array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.inc.h new file mode 100644 index 00000000..176fc26b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigInt64Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_BIGINT64_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGINT64ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.cpp new file mode 100644 index 00000000..9844fbd5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.cpp @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-biguint64array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID biguint64array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup biguint64arrayprototype ECMA BigUInt64Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.inc.h new file mode 100644 index 00000000..03626442 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigUInt64Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGUINT64ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.cpp new file mode 100644 index 00000000..2482ec2e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-biguint64array.inc.h" +#define BUILTIN_UNDERSCORED_ID biguint64array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup biguint64array ECMA BigUInt64Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of BigUInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_biguint64array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_BIG_UINT64_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_biguint64array_dispatch_call */ + +/** + * Handle calling [[Construct]] of BigUInt64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_biguint64array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_BIGUINT64_ARRAY); +} /* ecma_builtin_biguint64array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.inc.h new file mode 100644 index 00000000..ea38782a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.inc.h @@ -0,0 +1,29 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * BigUInt64Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_BUILTIN_BIGINT + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_BIGUINT64ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY && JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.cpp new file mode 100644 index 00000000..1e6a6041 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float32array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID float32array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float32arrayprototype ECMA Float32Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.inc.h new file mode 100644 index 00000000..56bfeeae --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float32Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT32ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.cpp new file mode 100644 index 00000000..f4f3959f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float32array.inc.h" +#define BUILTIN_UNDERSCORED_ID float32array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float32array ECMA Float32Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Float32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float32array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_FLOAT32_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_float32array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Float32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float32array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_FLOAT32_ARRAY); +} /* ecma_builtin_float32array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.inc.h new file mode 100644 index 00000000..832b5119 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float32array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float32Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_FLOAT32_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT32ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.cpp new file mode 100644 index 00000000..205d23a7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.cpp @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float64array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID float64array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float64arrayprototype ECMA Float64Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.inc.h new file mode 100644 index 00000000..815be714 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.inc.h @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float64Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT64ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.cpp new file mode 100644 index 00000000..fe3cebb8 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-float64array.inc.h" +#define BUILTIN_UNDERSCORED_ID float64array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup float64array ECMA Float64Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Float64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float64array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_FLOAT64_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_float64array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Float64Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_float64array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_FLOAT64_ARRAY); +} /* ecma_builtin_float64array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.inc.h new file mode 100644 index 00000000..ea8bd422 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-float64array.inc.h @@ -0,0 +1,29 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Float64Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY +#if JERRY_NUMBER_TYPE_FLOAT64 + +#define TYPEDARRAY_BYTES_PER_ELEMENT 8 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_FLOAT64_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_FLOAT64ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.cpp new file mode 100644 index 00000000..1b9c435b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int16array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID int16array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int16arrayprototype ECMA Int16Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.inc.h new file mode 100644 index 00000000..7815d9a5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int16Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT16ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.cpp new file mode 100644 index 00000000..076a853b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int16array.inc.h" +#define BUILTIN_UNDERSCORED_ID int16array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int64array ECMA Int16Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Int16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int16array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_INT16_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_int16array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Int16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int16array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_INT16_ARRAY); +} /* ecma_builtin_int16array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.inc.h new file mode 100644 index 00000000..f744ed77 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int16array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int16Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_INT16_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT16ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.cpp new file mode 100644 index 00000000..36fc8470 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int32array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID int32array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int32arrayprototype ECMA Int32Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.inc.h new file mode 100644 index 00000000..9a31a062 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int32Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT32ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.cpp new file mode 100644 index 00000000..a322a301 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int32array.inc.h" +#define BUILTIN_UNDERSCORED_ID int32array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int32array ECMA Int32Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Int32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int32array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_INT32_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_int32array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Int32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int32array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_INT32_ARRAY); +} /* ecma_builtin_int32array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.inc.h new file mode 100644 index 00000000..ac786a0b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int32array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int32Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_INT32_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT32ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.cpp new file mode 100644 index 00000000..8221f309 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int8array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID int8array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int8arrayprototype ECMA Int8Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.inc.h new file mode 100644 index 00000000..99d072b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int8Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT8ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.cpp new file mode 100644 index 00000000..402e3838 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-int8array.inc.h" +#define BUILTIN_UNDERSCORED_ID int8array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup int8array ECMA Int8Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Int8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int8array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_INT8_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_int8array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Int8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_int8array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_INT8_ARRAY); +} /* ecma_builtin_int8array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.inc.h new file mode 100644 index 00000000..25c84de2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-int8array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Int8Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_INT8_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.cpp new file mode 100644 index 00000000..23681ddb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.cpp @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-typedarray-helpers.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-objects.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * Common implementation of the [[Construct]] call of TypedArrays. + * + * @return ecma value of the new TypedArray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_typedarray_helper_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len, /**< number of arguments */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + ecma_builtin_id_t proto_id = ecma_typedarray_helper_get_prototype_id (typedarray_id); + ecma_object_t *prototype_obj_p = NULL; + ecma_object_t *current_new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (current_new_target_p != NULL) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (current_new_target_p, proto_id); + if (prototype_obj_p == NULL) + { + return ECMA_VALUE_ERROR; + } + } + else + { + prototype_obj_p = ecma_builtin_get (proto_id); + } + + ecma_value_t val = ecma_op_create_typedarray (arguments_list_p, + arguments_list_len, + prototype_obj_p, + ecma_typedarray_helper_get_shift_size (typedarray_id), + typedarray_id); + + if (current_new_target_p != NULL) + { + ecma_deref_object (prototype_obj_p); + } + + return val; +} /* ecma_typedarray_helper_dispatch_construct */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h new file mode 100644 index 00000000..d4064374 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_TYPEDARRAY_HELPERS_H +#define ECMA_TYPEDARRAY_HELPERS_H +#include "ecma-globals.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations + * @{ + */ + +ecma_value_t ecma_typedarray_helper_dispatch_construct (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + ecma_typedarray_type_t typedarray_id); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#endif /* !ECMA_TYPEDARRAY_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype-template.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype-template.inc.h new file mode 100644 index 00000000..beb63352 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype-template.inc.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#ifndef TYPEDARRAY_BYTES_PER_ELEMENT +#error "Please define TYPEDARRAY_BYTES_PER_ELEMENT" +#endif /* !TYPEDARRAY_BYTES_PER_ELEMENT */ + +#ifndef TYPEDARRAY_BUILTIN_ID +#error "Please define TYPEDARRAY_BUILTIN_ID" +#endif /* !TYPEDARRAY_BUILTIN_ID */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ES2015 22.2.3.4 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, TYPEDARRAY_BUILTIN_ID, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* ES2015 22.2.6.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U, TYPEDARRAY_BYTES_PER_ELEMENT, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" + +#undef TYPEDARRAY_BUILTIN_ID +#undef TYPEDARRAY_BYTES_PER_ELEMENT + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.cpp new file mode 100644 index 00000000..3738e175 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.cpp @@ -0,0 +1,2106 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtin-typedarray-helpers.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-number-object.h" +#include "ecma-objects.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" +#include "jrt.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + /* These routines must be in this order */ + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_START = 0, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_MAP, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SOME, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FOR_EACH, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX, + + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LAST_INDEX_OF, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILL, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SORT, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REVERSE, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_COPY_WITHIN, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SLICE, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_LOCALE_STRING, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_JOIN, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_ENTRIES, + + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTELENGTH_GETTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTEOFFSET_GETTER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LENGTH_GETTER, + + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SET, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER, +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typedarray-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID typedarray_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup typedarrayprototype ECMA %TypedArray%.prototype object built-in + * @{ + */ + +/** + * Type of routine. + */ +typedef enum +{ + TYPEDARRAY_ROUTINE_EVERY, /**< routine: every ES2015, 22.2.3.7 */ + TYPEDARRAY_ROUTINE_SOME, /**< routine: some ES2015, 22.2.3.9 */ + TYPEDARRAY_ROUTINE_FOREACH, /**< routine: forEach ES2015, 15.4.4.18 */ + TYPEDARRAY_ROUTINE__COUNT /**< count of the modes */ +} typedarray_routine_mode; + +/** + * The common function for 'every', 'some' and 'forEach' + * because they have a similar structure. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_exec_routine (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t cb_this_arg, /**< 'this' of the callback function */ + typedarray_routine_mode mode) /**< mode: which routine */ +{ + JERRY_ASSERT (mode < TYPEDARRAY_ROUTINE__COUNT); + + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint32_t byte_pos = 0; + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + for (uint32_t index = 0; index < info_p->length && ecma_is_value_empty (ret_value); index++) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t element = typedarray_getter_cb (buffer_p + byte_pos); + + ecma_value_t call_args[] = { element, current_index, this_arg }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + ecma_fast_free_value (current_index); + ecma_fast_free_value (element); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (call_value); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + bool to_bool_result = ecma_op_to_boolean (call_value); + ecma_free_value (call_value); + + if (mode == TYPEDARRAY_ROUTINE_EVERY) + { + if (!to_bool_result) + { + return ECMA_VALUE_FALSE; + } + } + else if (mode == TYPEDARRAY_ROUTINE_SOME && to_bool_result) + { + return ECMA_VALUE_TRUE; + } + + byte_pos += info_p->element_size; + } + + if (mode == TYPEDARRAY_ROUTINE_EVERY) + { + ret_value = ECMA_VALUE_TRUE; + } + else if (mode == TYPEDARRAY_ROUTINE_SOME) + { + ret_value = ECMA_VALUE_FALSE; + } + else + { + ret_value = ECMA_VALUE_UNDEFINED; + } + + return ret_value; +} /* ecma_builtin_typedarray_prototype_exec_routine */ + +/** + * The %TypedArray%.prototype object's 'map' routine + * + * See also: + * ES2015, 22.2.3.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *src_info_p, /**< object info */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t cb_this_arg) /**< this' of the callback function */ +{ + ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (src_info_p->array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (src_info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + // TODO: 22.2.3.18, 7-8. + ecma_value_t len = ecma_make_number_value (src_info_p->length); + ecma_value_t new_typedarray = ecma_typedarray_species_create (this_arg, &len, 1); + ecma_free_value (len); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + return new_typedarray; + } + + ecma_object_t *target_obj_p = ecma_get_object_from_value (new_typedarray); + + uint8_t *src_buffer_p = ecma_typedarray_get_buffer (src_info_p); + + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (target_obj_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p)) + { + ecma_deref_object (target_obj_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + ecma_deref_object (target_obj_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_info_p->id); + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + + for (uint32_t index = 0; index < src_info_p->length; index++) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t element = src_typedarray_getter_cb (src_buffer_p); + src_buffer_p += src_info_p->element_size; + + ecma_value_t call_args[] = { element, current_index, this_arg }; + ecma_value_t mapped_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + ecma_free_value (current_index); + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (mapped_value)) + { + ecma_free_value (new_typedarray); + return mapped_value; + } + + if (ecma_arraybuffer_is_detached (src_info_p->array_buffer_p)) + { + ecma_free_value (mapped_value); + ecma_free_value (new_typedarray); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, mapped_value); + target_buffer_p += target_info.element_size; + ecma_free_value (mapped_value); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_free_value (new_typedarray); + return set_element; + } + } + + return new_typedarray; +} /* ecma_builtin_typedarray_prototype_map */ + +/** + * Reduce and reduceRight routines share a similar structure. + * And we use 'is_right' to distinguish between them. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_reduce_with_direction (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t arguments_list_p[], /**arg_list*/ + uint32_t arguments_number, /**< length of arguments' list*/ + bool is_right) /**< choose order, true is reduceRight */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint32_t byte_pos; + + if (info_p->length == 0) + { + if (arguments_number < 2) + { + return ecma_raise_type_error (ECMA_ERR_INITIAL_VALUE_CANNOT_BE_UNDEFINED); + } + + return ecma_copy_value (arguments_list_p[1]); + } + + JERRY_ASSERT (info_p->length > 0); + + ecma_value_t accumulator = ECMA_VALUE_UNDEFINED; + uint32_t index = is_right ? (info_p->length - 1) : 0; + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + + if (ecma_is_value_undefined (arguments_list_p[1])) + { + byte_pos = index << info_p->shift; + accumulator = getter_cb (buffer_p + byte_pos); + + if (is_right) + { + if (index == 0) + { + return accumulator; + } + + index--; + } + else + { + index++; + + if (index == info_p->length) + { + return accumulator; + } + } + } + else + { + accumulator = ecma_copy_value (arguments_list_p[1]); + } + + ecma_object_t *func_object_p = ecma_get_object_from_value (arguments_list_p[0]); + + while (true) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + byte_pos = index << info_p->shift; + ecma_value_t get_value = getter_cb (buffer_p + byte_pos); + + ecma_value_t call_args[] = { accumulator, get_value, current_index, this_arg }; + + JERRY_ASSERT (ecma_is_value_number (get_value) || ecma_is_value_bigint (get_value)); + + ecma_value_t call_value = ecma_op_function_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); + + ecma_fast_free_value (accumulator); + ecma_fast_free_value (get_value); + ecma_fast_free_value (current_index); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (call_value); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + accumulator = call_value; + + if (is_right) + { + if (index == 0) + { + break; + } + + index--; + } + else + { + index++; + + if (index == info_p->length) + { + break; + } + } + } + + return accumulator; +} /* ecma_builtin_typedarray_prototype_reduce_with_direction */ + +/** + * The %TypedArray%.prototype object's 'filter' routine + * + * See also: + * ES2015, 22.2.3.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t cb_this_arg) /**< 'this' of the callback function */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + + ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + // TODO: 22.2.3.9, 7-8. + if (info_p->length == 0) + { + return ecma_op_create_typedarray_with_type_and_length (info_p->id, 0); + } + + ecma_collection_t *collected_p = ecma_new_collection (); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + ecma_value_t collected; + + for (uint32_t index = 0; index < info_p->length; index++) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t get_value = getter_cb (buffer_p); + + JERRY_ASSERT (ecma_is_value_number (get_value) || ecma_is_value_bigint (get_value)); + + ecma_value_t call_args[] = { get_value, current_index, this_arg }; + + ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + ecma_fast_free_value (current_index); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_fast_free_value (get_value); + goto cleanup; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (call_value); + ecma_fast_free_value (get_value); + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto cleanup; + } + + if (ecma_op_to_boolean (call_value)) + { + ecma_collection_push_back (collected_p, get_value); + } + else + { + ecma_fast_free_value (get_value); + } + + buffer_p += info_p->element_size; + ecma_fast_free_value (call_value); + } + + collected = ecma_make_number_value (collected_p->item_count); + ret_value = ecma_typedarray_species_create (this_arg, &collected, 1); + ecma_free_value (collected); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (ret_value); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (new_typedarray_p); + + JERRY_ASSERT (target_info.offset == 0); + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + + for (uint32_t idx = 0; idx < collected_p->item_count; idx++) + { + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, collected_p->buffer_p[idx]); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (new_typedarray_p); + ret_value = ECMA_VALUE_ERROR; + goto cleanup; + } + + target_buffer_p += target_info.element_size; + } + } + +cleanup: + ecma_collection_free (collected_p); + + return ret_value; +} /* ecma_builtin_typedarray_prototype_filter */ + +/** + * The %TypedArray%.prototype object's 'reverse' routine + * + * See also: + * ES2015, 22.2.3.21 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_reverse (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p) /**< object info */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint32_t middle = (info_p->length / 2) << info_p->shift; + uint32_t buffer_last = (info_p->length << info_p->shift) - info_p->element_size; + + for (uint32_t lower = 0; lower < middle; lower += info_p->element_size) + { + uint32_t upper = buffer_last - lower; + uint8_t *lower_p = buffer_p + lower; + uint8_t *upper_p = buffer_p + upper; + + uint8_t tmp[8]; + memcpy (&tmp[0], lower_p, info_p->element_size); + memcpy (lower_p, upper_p, info_p->element_size); + memcpy (upper_p, &tmp[0], info_p->element_size); + } + + return ecma_copy_value (this_arg); +} /* ecma_builtin_typedarray_prototype_reverse */ + +/** + * The %TypedArray%.prototype object's 'set' routine for a typedArray source + * + * See also: + * ES2015, 22.2.3.22, 22.2.3.22.2 + * + * @return ecma value of undefined if success, error otherwise. + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arr_val, /**< typedarray object */ + ecma_value_t offset_val) /**< offset value */ +{ + /* 6.~ 8. targetOffset */ + ecma_number_t target_offset_num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (offset_val, &target_offset_num))) + { + return ECMA_VALUE_ERROR; + } + + if (target_offset_num <= -1.0 || target_offset_num >= (ecma_number_t) UINT32_MAX + 0.5) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OFFSET); + } + + ecma_object_t *target_typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (target_typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + ecma_object_t *src_typedarray_p = ecma_get_object_from_value (arr_val); + ecma_typedarray_info_t src_info = ecma_typedarray_get_info (src_typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (src_info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (src_info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *src_buffer_p = ecma_typedarray_get_buffer (&src_info); + + uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num); + + if ((int64_t) src_info.length + target_offset_uint32 > target_info.length) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_RANGE_OF_INDEX); + } + + /* Fast path first. If the source and target arrays are the same we do not need to copy anything. */ + if (this_arg == arr_val) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 26. targetByteIndex */ + target_buffer_p += target_offset_uint32 << target_info.shift; + + /* 27. limit */ + uint32_t limit = src_info.length << target_info.shift; + + if (src_info.id == target_info.id) + { + memmove (target_buffer_p, src_buffer_p, limit); + } + else + { + uint8_t *target_limit_p = target_buffer_p + limit; + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_info.id); + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + + while (target_buffer_p < target_limit_p) + { + ecma_value_t element = src_typedarray_getter_cb (src_buffer_p); + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, element); + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + + src_buffer_p += src_info.element_size; + target_buffer_p += target_info.element_size; + } + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_typedarray_set_with_typedarray */ + +/** + * The %TypedArray%.prototype object's 'set' routine + * + * See also: + * ES2015, 22.2.3.22, 22.2.3.22.1 + * + * @return ecma value of undefined if success, error otherwise. + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arr_val, /**< array object */ + ecma_value_t offset_val) /**< offset value */ +{ + /* 1. */ + if (ecma_is_typedarray (arr_val)) + { + /* 22.2.3.22.2 */ + return ecma_op_typedarray_set_with_typedarray (this_arg, arr_val, offset_val); + } + + /* 6.~ 8. targetOffset */ + ecma_number_t target_offset_num; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (offset_val, &target_offset_num))) + { + return ECMA_VALUE_ERROR; + } + + if (target_offset_num <= -1.0 || target_offset_num >= (ecma_number_t) UINT32_MAX + 0.5) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OFFSET); + } + uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num); + + /* 11. ~ 15. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info); + + /* 16.~ 17. */ + ecma_value_t source_obj = ecma_op_to_object (arr_val); + + if (ECMA_IS_VALUE_ERROR (source_obj)) + { + return source_obj; + } + + /* 18.~ 19. */ + ecma_object_t *source_obj_p = ecma_get_object_from_value (source_obj); + + ecma_length_t source_length; + + if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (source_obj_p, &source_length))) + { + ecma_deref_object (source_obj_p); + return ECMA_VALUE_ERROR; + } + + /* 20. if srcLength + targetOffset > targetLength, throw a RangeError */ + if ((int64_t) source_length + target_offset_uint32 > target_info.length) + { + ecma_deref_object (source_obj_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_RANGE_OF_INDEX); + } + JERRY_ASSERT (source_length <= UINT32_MAX); + uint32_t source_length_uint32 = (uint32_t) source_length; + + /* 21.~ 25. */ + target_buffer_p += target_offset_uint32 << target_info.shift; + + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id); + uint32_t k = 0; + + while (k < source_length_uint32) + { + ecma_value_t elem = ecma_op_object_get_by_index (source_obj_p, k); + + if (ECMA_IS_VALUE_ERROR (elem)) + { + ecma_deref_object (source_obj_p); + return elem; + } + + ecma_value_t value_to_set; + +#if JERRY_BUILTIN_BIGINT + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (target_info.id)) + { + value_to_set = ecma_bigint_to_bigint (elem, false); + + if (ECMA_IS_VALUE_ERROR (value_to_set)) + { + ecma_deref_object (source_obj_p); + ecma_free_value (elem); + return value_to_set; + } + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_number_t elem_num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (elem, &elem_num, ECMA_TO_NUMERIC_NO_OPTS))) + { + ecma_free_value (elem); + ecma_deref_object (source_obj_p); + return ECMA_VALUE_ERROR; + } + + value_to_set = ecma_make_number_value (elem_num); + } + + ecma_free_value (elem); + + if (ecma_arraybuffer_is_detached (target_info.array_buffer_p)) + { + ecma_deref_object (source_obj_p); + ecma_free_value (value_to_set); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, value_to_set); + + ecma_free_value (value_to_set); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (source_obj_p); + return set_element; + } + + k++; + target_buffer_p += target_info.element_size; + } + + ecma_deref_object (source_obj_p); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_builtin_typedarray_prototype_set */ + +/** + * TypedArray.prototype's 'toString' single element operation routine based + * on the Array.prototype's 'toString' single element operation routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 + * + * @return NULL - if the converison fails + * ecma_string_t * - otherwise + */ +static ecma_string_t * +ecma_op_typedarray_get_to_string_at_index (ecma_object_t *obj_p, /**< this object */ + uint32_t index) /**< array index */ +{ + ecma_value_t index_value = ecma_op_object_get_by_index (obj_p, index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return NULL; + } + + if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) + { + ecma_free_value (index_value); + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *ret_str_p = ecma_op_to_string (index_value); + + ecma_free_value (index_value); + + return ret_str_p; +} /* ecma_op_typedarray_get_to_string_at_index */ + +/** + * The TypedArray.prototype.toString's separator creation routine based on + * the Array.prototype.toString's separator routine + * + * See also: + * ECMA-262 v5.1, 15.4.4.2 4th step + * + * @return NULL - if the conversion fails + * ecma_string_t * - otherwise + */ +static ecma_string_t * +ecma_op_typedarray_get_separator_string (ecma_value_t separator) /**< possible separator */ +{ + if (ecma_is_value_undefined (separator)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); + } + + return ecma_op_to_string (separator); +} /* ecma_op_typedarray_get_separator_string */ + +/** + * The TypedArray.prototype object's 'join' routine basen on + * the Array.porottype object's 'join' + * + * See also: + * ECMA-262 v5, 15.4.4.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_join (ecma_object_t *obj_p, /**< this object */ + ecma_value_t separator_arg) /**< separator argument */ +{ + ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p); + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 2. */ + uint32_t length = ecma_typedarray_get_length (obj_p); + ecma_string_t *separator_string_p = ecma_op_typedarray_get_separator_string (separator_arg); + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + if (JERRY_UNLIKELY (separator_string_p == NULL)) + { + return ret_value; + } + + /* 7-8. */ + ecma_string_t *first_string_p = ecma_op_typedarray_get_to_string_at_index (obj_p, 0); + + if (JERRY_UNLIKELY (first_string_p == NULL)) + { + ecma_deref_ecma_string (separator_string_p); + return ret_value; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (first_string_p); + + ecma_deref_ecma_string (first_string_p); + + /* 9-10. */ + for (uint32_t k = 1; k < length; k++) + { + /* 10.a */ + ecma_stringbuilder_append (&builder, separator_string_p); + + /* 10.d */ + ecma_string_t *next_string_p = ecma_op_typedarray_get_to_string_at_index (obj_p, k); + + if (JERRY_UNLIKELY (next_string_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + ecma_deref_ecma_string (separator_string_p); + return ret_value; + } + + ecma_stringbuilder_append (&builder, next_string_p); + + ecma_deref_ecma_string (next_string_p); + } + + ecma_deref_ecma_string (separator_string_p); + ret_value = ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); + + return ret_value; +} /* ecma_builtin_typedarray_prototype_join */ + +/** + * The %TypedArray%.prototype object's 'subarray' routine. + * + * See also: + * ES2015, 22.2.3.26 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_subarray (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t begin, /**< begin */ + ecma_value_t end) /**< end */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 9. beginIndex, 12. endIndex */ + uint32_t begin_index_uint32 = 0, end_index_uint32 = 0; + + /* 7. relativeBegin */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (begin, info_p->length, &begin_index_uint32))) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_is_value_undefined (end)) + { + end_index_uint32 = (uint32_t) info_p->length; + } + else + { + /* 10. relativeEnd */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (end, info_p->length, &end_index_uint32))) + { + return ECMA_VALUE_ERROR; + } + } + + /* 13. newLength */ + uint32_t subarray_length = 0; + + if (end_index_uint32 > begin_index_uint32) + { + subarray_length = end_index_uint32 - begin_index_uint32; + } + + /* 17. beginByteOffset */ + uint32_t begin_byte_offset = info_p->offset + (begin_index_uint32 << info_p->shift); + + ecma_value_t arguments_p[3] = { ecma_make_object_value (info_p->array_buffer_p), + ecma_make_uint32_value (begin_byte_offset), + ecma_make_uint32_value (subarray_length) }; + + ret_value = ecma_typedarray_species_create (this_arg, arguments_p, 3); + + ecma_free_value (arguments_p[1]); + ecma_free_value (arguments_p[2]); + return ret_value; +} /* ecma_builtin_typedarray_prototype_subarray */ + +/** + * The %TypedArray%.prototype object's 'fill' routine. + * + * See also: + * ES2015, 22.2.3.8, 22.1.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this object */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t value, /**< value */ + ecma_value_t begin, /**< begin */ + ecma_value_t end) /**< end */ +{ + ecma_value_t value_to_set; + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + +#if JERRY_BUILTIN_BIGINT + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id)) + { + value_to_set = ecma_bigint_to_bigint (value, true); + + if (ECMA_IS_VALUE_ERROR (value_to_set)) + { + return value_to_set; + } + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_number_t value_num; + ecma_value_t ret_value = ecma_op_to_numeric (value, &value_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (!ecma_is_value_empty (ret_value)) + { + return ret_value; + } + + value_to_set = ecma_make_number_value (value_num); + } + + uint32_t begin_index_uint32 = 0, end_index_uint32 = 0; + + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (begin, info_p->length, &begin_index_uint32))) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + + if (ecma_is_value_undefined (end)) + { + end_index_uint32 = (uint32_t) info_p->length; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (end, info_p->length, &end_index_uint32))) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + } + + uint32_t subarray_length = 0; + + if (end_index_uint32 > begin_index_uint32) + { + subarray_length = end_index_uint32 - begin_index_uint32; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + buffer_p += begin_index_uint32 << info_p->shift; + + uint8_t *limit_p = buffer_p + (subarray_length << info_p->shift); + ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info_p->id); + + while (buffer_p < limit_p) + { + ecma_value_t set_element = typedarray_setter_cb (buffer_p, value_to_set); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_free_value (value_to_set); + return set_element; + } + + buffer_p += info_p->element_size; + } + + ecma_free_value (value_to_set); + + return ecma_copy_value (this_arg); +} /* ecma_builtin_typedarray_prototype_fill */ + +/** + * SortCompare abstract method + * + * See also: + * ECMA-262 v5, 15.4.4.11 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_sort_compare_helper (ecma_value_t lhs, /**< left value */ + ecma_value_t rhs, /**< right value */ + ecma_value_t compare_func, /**< compare function */ + ecma_object_t *array_buffer_p) /**< array buffer */ +{ + if (ecma_is_value_undefined (compare_func)) + { + /* Default comparison when no comparefn is passed. */ +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (lhs) && ecma_is_value_bigint (rhs)) + { + return ecma_make_number_value (ecma_bigint_compare_to_bigint (lhs, rhs)); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + ecma_number_t result = ECMA_NUMBER_ZERO; + + double lhs_value = (double) ecma_get_number_from_value (lhs); + double rhs_value = (double) ecma_get_number_from_value (rhs); + + if (ecma_number_is_nan (lhs_value)) + { + // Keep NaNs at the end of the array. + result = ECMA_NUMBER_ONE; + } + else if (ecma_number_is_nan (rhs_value)) + { + // Keep NaNs at the end of the array. + result = ECMA_NUMBER_MINUS_ONE; + } + else if (lhs_value < rhs_value) + { + result = ECMA_NUMBER_MINUS_ONE; + } + else if (lhs_value > rhs_value || (ecma_number_is_zero (rhs_value) && ecma_number_is_negative (rhs_value))) + { + result = ECMA_NUMBER_ONE; + } + else + { + result = ECMA_NUMBER_ZERO; + } + + return ecma_make_number_value (result); + } + + /* + * compare_func, if not undefined, will always contain a callable function object. + * We checked this previously, before this function was called. + */ + JERRY_ASSERT (ecma_op_is_callable (compare_func)); + ecma_object_t *comparefn_obj_p = ecma_get_object_from_value (compare_func); + + ecma_value_t compare_args[] = { lhs, rhs }; + + ecma_value_t call_value = ecma_op_function_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); + + if (ECMA_IS_VALUE_ERROR (call_value) || ecma_is_value_number (call_value)) + { + return call_value; + } + + ecma_number_t ret_num; + ecma_value_t number_result = ecma_op_to_number (call_value, &ret_num); + + ecma_free_value (call_value); + + if (ECMA_IS_VALUE_ERROR (number_result)) + { + return number_result; + } + + if (ecma_arraybuffer_is_detached (array_buffer_p)) + { + ecma_free_value (number_result); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + // If the coerced value can't be represented as a Number, compare them as equals. + if (ecma_number_is_nan (ret_num)) + { + return ecma_make_number_value (ECMA_NUMBER_ZERO); + } + + return ecma_make_number_value (ret_num); +} /* ecma_builtin_typedarray_prototype_sort_compare_helper */ + +/** + * The %TypedArray%.prototype object's 'sort' routine. + * + * See also: + * ES2015, 22.2.3.25, 22.1.3.24 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_sort (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t compare_func) /**< comparator fn */ +{ + JERRY_ASSERT (ecma_is_typedarray (this_arg)); + JERRY_ASSERT (ecma_is_value_undefined (compare_func) || ecma_op_is_callable (compare_func)); + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (!info_p->length) + { + return ecma_copy_value (this_arg); + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + JMEM_DEFINE_LOCAL_ARRAY (values_buffer, info_p->length, ecma_value_t); + + uint32_t buffer_index = 0; + + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + ecma_typedarray_setter_fn_t typedarray_setter_cb; + + /* Copy unsorted array into a native c array. */ + while (buffer_p < limit_p) + { + JERRY_ASSERT (buffer_index < info_p->length); + ecma_value_t element_value = typedarray_getter_cb (buffer_p); + values_buffer[buffer_index++] = element_value; + buffer_p += info_p->element_size; + } + + JERRY_ASSERT (buffer_index == info_p->length); + + const ecma_builtin_helper_sort_compare_fn_t sort_cb = &ecma_builtin_typedarray_prototype_sort_compare_helper; + + ecma_value_t sort_value = ecma_builtin_helper_array_merge_sort_helper (values_buffer, + (uint32_t) (info_p->length), + compare_func, + sort_cb, + info_p->array_buffer_p); + + if (ECMA_IS_VALUE_ERROR (sort_value)) + { + ret_value = sort_value; + goto free_values; + } + + JERRY_ASSERT (sort_value == ECMA_VALUE_EMPTY); + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + typedarray_setter_cb = ecma_get_typedarray_setter_fn (info_p->id); + + buffer_p = limit_p - (info_p->length << info_p->shift); + buffer_index = 0; + + /* Put sorted values from the native array back into the typedarray buffer. */ + while (buffer_p < limit_p) + { + JERRY_ASSERT (buffer_index < info_p->length); + ecma_value_t element_value = values_buffer[buffer_index++]; + ecma_value_t set_element = typedarray_setter_cb (buffer_p, element_value); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ret_value = set_element; + goto free_values; + } + + buffer_p += info_p->element_size; + } + + JERRY_ASSERT (buffer_index == info_p->length); + + ret_value = ecma_copy_value (this_arg); + +free_values: + /* Free values that were copied to the local array. */ + for (uint32_t index = 0; index < info_p->length; index++) + { + ecma_free_value (values_buffer[index]); + } + + JMEM_FINALIZE_LOCAL_ARRAY (values_buffer); + + return ret_value; +} /* ecma_builtin_typedarray_prototype_sort */ + +/** + * The %TypedArray%.prototype object's 'find' and 'findIndex' routine helper + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_find_helper (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + ecma_value_t predicate, /**< callback function */ + ecma_value_t predicate_this_arg, /**< this argument for + * invoke predicate */ + bool is_find) /**< true - find routine + * false - findIndex routine */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + JERRY_ASSERT (ecma_is_value_object (predicate)); + ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint32_t buffer_index = 0; + + while (buffer_p < limit_p) + { + JERRY_ASSERT (buffer_index < info_p->length); + ecma_value_t element_value = typedarray_getter_cb (buffer_p); + buffer_p += info_p->element_size; + + ecma_value_t call_args[] = { element_value, ecma_make_uint32_value (buffer_index), this_arg }; + ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ecma_free_value (element_value); + return call_value; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_free_value (element_value); + ecma_free_value (call_value); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + bool call_result = ecma_op_to_boolean (call_value); + ecma_free_value (call_value); + + if (call_result) + { + if (is_find) + { + return element_value; + } + + ecma_free_value (element_value); + return ecma_make_uint32_value (buffer_index); + } + + buffer_index++; + ecma_free_value (element_value); + } + + return is_find ? ECMA_VALUE_UNDEFINED : ecma_make_integer_value (-1); +} /* ecma_builtin_typedarray_prototype_find_helper */ + +/** + * The %TypedArray%.prototype object's 'at' routine + * + * See also: + * ECMA-262 Stage 3 Draft Relative Indexing Method proposal + * from: https://tc39.es/proposal-relative-indexing-method + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_at (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t index) /**< index argument */ +{ + ecma_length_t len = info_p->length; + ecma_length_t res_index; + ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index); + + if (return_value != ECMA_VALUE_EMPTY) + { + return return_value; + } + + if (res_index >= UINT32_MAX) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_get_typedarray_element (info_p, (uint32_t) res_index); +} /* ecma_builtin_typedarray_prototype_at */ + +/** + * The %TypedArray%.prototype object's 'indexOf' routine + * + * See also: + * ECMA-262 v6, 22.2.3.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_index_of (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + +#if JERRY_BUILTIN_BIGINT + bool is_bigint = ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id); +#else /* !JERRY_BUILTIN_BIGINT */ + bool is_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + uint32_t from_index; + + /* 5. */ + if (args_number == 0 || (!ecma_is_value_number (args[0]) && !is_bigint) || info_p->length == 0) + { + return ecma_make_integer_value (-1); + } + if (args_number == 1) + { + from_index = 0; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &from_index))) + { + return ECMA_VALUE_ERROR; + } + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + + buffer_p += from_index << info_p->shift; + + /* 11. */ + while (buffer_p < limit_p) + { + ecma_value_t element = getter_cb (buffer_p); + + if (ecma_op_same_value_zero (args[0], element, true)) + { + ecma_free_value (element); + return ecma_make_number_value (from_index); + } + + ecma_free_value (element); + buffer_p += info_p->element_size; + from_index++; + } + + /* 12. */ + return ecma_make_integer_value (-1); +} /* ecma_builtin_typedarray_prototype_index_of */ + +/** + * The %TypedArray%.prototype object's 'lastIndexOf' routine + * + * See also: + * ECMA-262 v6, 22.2.3.16 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_last_index_of (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + +#if JERRY_BUILTIN_BIGINT + bool is_bigint = ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id); +#else /* !JERRY_BUILTIN_BIGINT */ + bool is_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + uint32_t from_index; + + /* 5. */ + if (args_number == 0 || (!ecma_is_value_number (args[0]) && !is_bigint) || info_p->length == 0) + { + return ecma_make_integer_value (-1); + } + + if (args_number == 1) + { + from_index = info_p->length - 1; + } + else + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &from_index))) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t to_int; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &to_int))) + { + return ECMA_VALUE_ERROR; + } + + if (info_p->length + to_int < 0) + { + return ecma_make_integer_value (-1); + } + + from_index = JERRY_MIN (from_index, info_p->length - 1); + } + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; + uint8_t *current_element_p = buffer_p + (from_index << info_p->shift); + + /* 10. */ + while (current_element_p >= buffer_p) + { + ecma_value_t element = getter_cb (current_element_p); + + if (ecma_op_same_value_zero (args[0], element, true)) + { + ecma_free_value (element); + return ecma_make_number_value ((ecma_number_t) from_index); + } + + ecma_free_value (element); + current_element_p -= info_p->element_size; + from_index--; + } + + /* 11. */ + return ecma_make_integer_value (-1); +} /* ecma_builtin_typedarray_prototype_last_index_of */ + +/** + * The %TypedArray%.prototype object's 'copyWithin' routine + * + * See also: + * ECMA-262 v6, 22.2.3.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_copy_within (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint32_t relative_target = 0; + uint32_t relative_start = 0; + uint32_t relative_end = info_p->length; + + if (args_number > 0) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[0], info_p->length, &relative_target))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &relative_start))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 2 && args[2] != ECMA_VALUE_UNDEFINED) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[2], info_p->length, &relative_end))) + { + return ECMA_VALUE_ERROR; + } + } + } + } + + if (relative_target >= info_p->length || relative_start >= relative_end || relative_end == 0) + { + return ecma_copy_value (this_arg); + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + uint32_t distance = relative_end - relative_start; + uint32_t offset = info_p->length - relative_target; + uint32_t count = JERRY_MIN (distance, offset); + + memmove (buffer_p + (relative_target << info_p->shift), + buffer_p + (relative_start << info_p->shift), + (size_t) (count << info_p->shift)); + + return ecma_copy_value (this_arg); +} /* ecma_builtin_typedarray_prototype_copy_within */ + +/** + * The %TypedArray%.prototype object's 'slice' routine + * + * See also: + * ECMA-262 v6, 22.2.3.23 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argument */ + ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + uint32_t relative_start = 0; + uint32_t relative_end = info_p->length; + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (args_number > 0) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[0], info_p->length, &relative_start))) + { + return ECMA_VALUE_ERROR; + } + + if (args_number > 1 && args[1] != ECMA_VALUE_UNDEFINED + && ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &relative_end))) + { + return ECMA_VALUE_ERROR; + } + } + + uint8_t *src_buffer_p = ecma_typedarray_get_buffer (info_p); + + int32_t distance = (int32_t) (relative_end - relative_start); + uint32_t count = distance > 0 ? (uint32_t) distance : 0; + + ecma_value_t len = ecma_make_number_value (count); + // TODO: 22.2.3.23, 12-13. + ecma_value_t new_typedarray = ecma_typedarray_species_create (this_arg, &len, 1); + ecma_free_value (len); + + if (ECMA_IS_VALUE_ERROR (new_typedarray) || count == 0) + { + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_typedarray_info_t new_typedarray_info = ecma_typedarray_get_info (new_typedarray_p); + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + ecma_deref_object (new_typedarray_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + uint8_t *dst_buffer_p = ecma_typedarray_get_buffer (&new_typedarray_info); + + JERRY_ASSERT (new_typedarray_info.offset == 0); + + src_buffer_p += relative_start << info_p->shift; + + if (info_p->id == new_typedarray_info.id) + { + // 22.2.3.23. Step 22. h-i. + memcpy (dst_buffer_p, src_buffer_p, count << info_p->shift); + } + else + { + // 22.2.3.23. Step 21. b. + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + ecma_typedarray_setter_fn_t new_typedarray_setter_cb = ecma_get_typedarray_setter_fn (new_typedarray_info.id); + + for (uint32_t idx = 0; idx < count; idx++) + { + ecma_value_t element = src_typedarray_getter_cb (src_buffer_p); + ecma_value_t set_element = new_typedarray_setter_cb (dst_buffer_p, element); + ecma_free_value (element); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (new_typedarray_p); + return set_element; + } + + src_buffer_p += info_p->element_size; + dst_buffer_p += new_typedarray_info.element_size; + } + } + + return new_typedarray; +} /* ecma_builtin_typedarray_prototype_slice */ + +/** + * The TypedArray.prototype's 'toLocaleString' single element operation routine. + * + * See also: + * ECMA-262 v6, 22.1.3.26 steps 7-10 and 12.b-e + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_to_locale_string_helper (ecma_typedarray_info_t *info_p, /**< object info */ + uint32_t index) /** array index */ +{ + ecma_value_t element_value = ecma_get_typedarray_element (info_p, index); + + if (ECMA_IS_VALUE_ERROR (element_value)) + { + return element_value; + } + + ecma_value_t call_value = ecma_op_invoke_by_magic_id (element_value, LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, NULL, 0); + + ecma_free_value (element_value); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + ecma_string_t *str_p = ecma_op_to_string (call_value); + + ecma_free_value (call_value); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_make_string_value (str_p); +} /* ecma_builtin_typedarray_prototype_to_locale_string_helper */ + +/** + * The %TypedArray%.prototype object's 'toLocaleString' routine + * + * See also: + * ECMA-262 v6, 22.2.3.27 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_to_locale_string (ecma_typedarray_info_t *info_p) /**< object info */ +{ + if (info_p->length == 0) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t first_element = ecma_builtin_typedarray_prototype_to_locale_string_helper (info_p, 0); + + if (ECMA_IS_VALUE_ERROR (first_element)) + { + return first_element; + } + + ecma_string_t *return_string_p = ecma_get_string_from_value (first_element); + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (return_string_p); + ecma_deref_ecma_string (return_string_p); + + for (uint32_t k = 1; k < info_p->length; k++) + { + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COMMA); + ecma_value_t next_element = ecma_builtin_typedarray_prototype_to_locale_string_helper (info_p, k); + + if (ECMA_IS_VALUE_ERROR (next_element)) + { + ecma_stringbuilder_destroy (&builder); + return next_element; + } + + ecma_string_t *next_element_p = ecma_get_string_from_value (next_element); + ecma_stringbuilder_append (&builder, next_element_p); + ecma_deref_ecma_string (next_element_p); + } + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_builtin_typedarray_prototype_to_locale_string */ + +/** + * The %TypedArray%.prototype object's 'includes' routine + * + * See also: + * ECMA-262 v11, 22.2.3.13. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_includes (ecma_typedarray_info_t *info_p, /**< object info */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ +#if JERRY_BUILTIN_BIGINT + bool is_bigint = ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id); +#else /* !JERRRY_BUILTIN_BIGINT */ + bool is_bigint = false; +#endif /* JERRRY_BUILTIN_BIGINT */ + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (args_number == 0 || (!ecma_is_value_number (args[0]) && !is_bigint) || info_p->length == 0) + { + return ECMA_VALUE_FALSE; + } + + uint32_t from_index = 0; + + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (args[1], info_p->length, &from_index))) + { + return ECMA_VALUE_ERROR; + } + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id); + uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift); + + buffer_p += from_index << info_p->shift; + + while (buffer_p < limit_p) + { + ecma_value_t element = getter_cb (buffer_p); + + if (ecma_op_same_value_zero (args[0], element, false)) + { + ecma_free_value (element); + return ECMA_VALUE_TRUE; + } + + ecma_free_value (element); + buffer_p += info_p->element_size; + } + + return ECMA_VALUE_FALSE; +} /* ecma_builtin_typedarray_prototype_includes */ + +/** + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_typedarray_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide + * routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + uint32_t arguments_number) /**< length of arguments' list */ +{ + if (!ecma_is_typedarray (this_arg)) + { + if (builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY); + } + + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = { 0 }; + + if (builtin_routine_id < ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER) + { + info = ecma_typedarray_get_info (typedarray_p); + + if (builtin_routine_id != ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY + && ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + } + + if (builtin_routine_id < ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF && !ecma_op_is_callable (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + switch (builtin_routine_id) + { + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES: + { + return ecma_builtin_typedarray_prototype_includes (&info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_JOIN: + { + return ecma_builtin_typedarray_prototype_join (typedarray_p, arguments_list_p[0]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SOME: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FOR_EACH: + { + uint8_t offset = (uint8_t) (builtin_routine_id - ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY); + + return ecma_builtin_typedarray_prototype_exec_routine (this_arg, + &info, + arguments_list_p[0], + arguments_list_p[1], + (typedarray_routine_mode) offset); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_MAP: + { + return ecma_builtin_typedarray_prototype_map (this_arg, &info, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT: + { + bool is_reduce = builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT; + return ecma_builtin_typedarray_prototype_reduce_with_direction (this_arg, + &info, + arguments_list_p, + arguments_number, + is_reduce); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILTER: + { + return ecma_builtin_typedarray_prototype_filter (this_arg, &info, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REVERSE: + { + return ecma_builtin_typedarray_prototype_reverse (this_arg, &info); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SET: + { + return ecma_builtin_typedarray_prototype_set (this_arg, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY: + { + return ecma_builtin_typedarray_prototype_subarray (this_arg, &info, arguments_list_p[0], arguments_list_p[1]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILL: + { + return ecma_builtin_typedarray_prototype_fill (this_arg, + &info, + arguments_list_p[0], + arguments_list_p[1], + arguments_list_p[2]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SORT: + { + if (!ecma_is_value_undefined (arguments_list_p[0]) && !ecma_op_is_callable (arguments_list_p[0])) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + return ecma_builtin_typedarray_prototype_sort (this_arg, &info, arguments_list_p[0]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX: + { + bool is_find = builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND; + return ecma_builtin_typedarray_prototype_find_helper (this_arg, + &info, + arguments_list_p[0], + arguments_list_p[1], + is_find); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT: + { + return ecma_builtin_typedarray_prototype_at (&info, arguments_list_p[0]); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF: + { + return ecma_builtin_typedarray_prototype_index_of (&info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LAST_INDEX_OF: + { + return ecma_builtin_typedarray_prototype_last_index_of (&info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_COPY_WITHIN: + { + return ecma_builtin_typedarray_prototype_copy_within (this_arg, &info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SLICE: + { + return ecma_builtin_typedarray_prototype_slice (this_arg, &info, arguments_list_p, arguments_number); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_LOCALE_STRING: + { + return ecma_builtin_typedarray_prototype_to_locale_string (&info); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS: + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_ENTRIES: + { + ecma_iterator_kind_t iter_id = + (builtin_routine_id == ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS) ? ECMA_ITERATOR_KEYS : ECMA_ITERATOR_ENTRIES; + + return ecma_typedarray_iterators_helper (this_arg, iter_id); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER: + { + ecma_object_t *buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + ecma_ref_object (buffer_p); + + return ecma_make_object_value (buffer_p); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTELENGTH_GETTER: + { + ecma_object_t *buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + return ecma_make_uint32_value (0); + } + + uint32_t length = ecma_typedarray_get_length (typedarray_p); + uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p); + return ecma_make_uint32_value (length << shift); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTEOFFSET_GETTER: + { + return ecma_make_uint32_value (ecma_typedarray_get_offset (typedarray_p)); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LENGTH_GETTER: + { + ecma_object_t *buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + return ecma_make_uint32_value (0); + } + + return ecma_make_uint32_value (ecma_typedarray_get_length (typedarray_p)); + } + case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER: + { + ecma_extended_object_t *object_p = (ecma_extended_object_t *) typedarray_p; + return ecma_make_magic_string_value (ecma_get_typedarray_magic_string_id ((ecma_typedarray_type_t) object_p->u.cls.u1.typedarray_type)); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_typedarray_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h new file mode 100644 index 00000000..9cace683 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %TypedArrayPrototype% description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* ES2015 22.2.3.4 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_TYPEDARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +/* Readonly accessor properties */ +/* ES2015 22.2.3.1 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BUFFER, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BUFFER_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +/* ES2015 22.2.3.2 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTELENGTH_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +/* ES2015 22.2.3.3 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_OFFSET_UL, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_BYTEOFFSET_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.3.17 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_LENGTH, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LENGTH_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ECMA-262 v6, 23.1.3.13 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_STRING_TAG_GETTER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_COPY_WITHIN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_EVERY, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_EVERY, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FILL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILL, 3, 1) +ROUTINE (LIT_MAGIC_STRING_FILTER, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILTER, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FOR_EACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_AT, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_JOIN, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_JOIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS, 0, 0) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LAST_INDEX_OF, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_MAP, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_MAP, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REDUCE_RIGHT, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REVERSE, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_REVERSE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SET, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SET, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SLICE, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_SOME, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SOME, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SORT, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SORT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SUBARRAY, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY, 2, 2) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_TO_LOCALE_STRING, 0, 0) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_STRING_UL, LIT_MAGIC_STRING_TO_STRING_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, + LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, + LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-template.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-template.inc.h new file mode 100644 index 00000000..7c9313fc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-template.inc.h @@ -0,0 +1,50 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#ifndef TYPEDARRAY_BYTES_PER_ELEMENT +#error "Please define TYPEDARRAY_BYTES_PER_ELEMENT" +#endif /* !TYPEDARRAY_BYTES_PER_ELEMENT */ + +#ifndef TYPEDARRAY_MAGIC_STRING_ID +#error "Please define TYPEDARRAY_MAGIC_STRING_ID" +#endif /* !TYPEDARRAY_MAGIC_STRING_ID */ + +#ifndef TYPEDARRAY_BUILTIN_ID +#error "Please define TYPEDARRAY_BUILTIN_ID" +#endif /* !TYPEDARRAY_BUILTIN_ID */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +/* ES2015 22.2.5 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 3, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.5.1 */ +NUMBER_VALUE (LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U, TYPEDARRAY_BYTES_PER_ELEMENT, ECMA_PROPERTY_FIXED) + +/* ES2015 22.2.5 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, TYPEDARRAY_MAGIC_STRING_ID, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.5.2 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, TYPEDARRAY_BUILTIN_ID, ECMA_PROPERTY_FIXED) + +#include "ecma-builtin-helpers-macro-undefs.inc.h" + +#undef TYPEDARRAY_BUILTIN_ID +#undef TYPEDARRAY_MAGIC_STRING_ID +#undef TYPEDARRAY_BYTES_PER_ELEMENT + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.cpp new file mode 100644 index 00000000..c91f9764 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.cpp @@ -0,0 +1,215 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-typedarray.inc.h" +#define BUILTIN_UNDERSCORED_ID typedarray +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup typedarray ECMA %TypedArray% object built-in + * @{ + */ + +/** + * The %TypedArray%.from routine + * + * See also: + * ES2015 22.2.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_from (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (!ecma_is_constructor (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR); + } + + ecma_value_t source; + ecma_value_t map_fn = ECMA_VALUE_UNDEFINED; + ecma_value_t this_in_fn = ECMA_VALUE_UNDEFINED; + + if (arguments_list_len == 0) + { + return ecma_raise_type_error (ECMA_ERR_NO_SOURCE_ARGUMENT); + } + + source = arguments_list_p[0]; + + if (arguments_list_len > 1) + { + map_fn = arguments_list_p[1]; + + if (!ecma_op_is_callable (map_fn)) + { + return ecma_raise_type_error (ECMA_ERR_THE_MAPFN_ARGUMENT_IS_NOT_CALLABLE); + } + + if (arguments_list_len > 2) + { + this_in_fn = arguments_list_p[2]; + } + } + + return ecma_op_typedarray_from (this_arg, source, map_fn, this_in_fn); + +} /* ecma_builtin_typedarray_from */ + +/** + * The %TypedArray%.of routine + * + * See also: + * ES2015 22.2.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_of (ecma_value_t this_arg, /**< 'this' argument */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + if (!ecma_is_constructor (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_CONSTRUCTOR); + } + + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (this_arg); + ecma_value_t len_val = ecma_make_uint32_value (arguments_list_len); + ecma_value_t ret_val = ecma_typedarray_create (constructor_obj_p, &len_val, 1); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + return ret_val; + } + + uint32_t k = 0; + ecma_object_t *ret_obj_p = ecma_get_object_from_value (ret_val); + ecma_typedarray_info_t info = ecma_typedarray_get_info (ret_obj_p); + ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + ecma_deref_object (ret_obj_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_deref_object (ret_obj_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + lit_utf8_byte_t *buffer_p = ecma_typedarray_get_buffer (&info); + + while (k < arguments_list_len) + { + ecma_value_t set_element = setter_cb (buffer_p, arguments_list_p[k]); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (ret_obj_p); + return set_element; + } + + k++; + buffer_p += info.element_size; + } + + return ret_val; +} /* ecma_builtin_typedarray_of */ + +/** + * Handle calling [[Call]] of built-in %TypedArray% object + * + * ES2015 22.2.1 If %TypedArray% is directly called or + * called as part of a new expression an exception is thrown + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_typedarray_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_TYPEDARRAY_INTRINSTIC_DIRECTLY_CALLED); +} /* ecma_builtin_typedarray_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in %TypedArray% object + * + * ES2015 22.2.1 If %TypedArray% is directly called or + * called as part of a new expression an exception is thrown + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_typedarray_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_TYPEDARRAY_INTRINSTIC_CALLED_BY_NEW_EXPRESSION); +} /* ecma_builtin_typedarray_dispatch_construct */ + +/** + * 22.2.2.4 get %TypedArray% [ @@species ] accessor + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_builtin_typedarray_species_get (ecma_value_t this_value) /**< This Value */ +{ + return ecma_copy_value (this_value); +} /* ecma_builtin_typedarray_species_get */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.inc.h new file mode 100644 index 00000000..bc8ab47d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.inc.h @@ -0,0 +1,48 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %TypedArray% description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/* ES2015 22.2.2 */ +/* ES11 22.2.1.1 - value of length changed to 0 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.2 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, LIT_MAGIC_STRING_TYPED_ARRAY_UL, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* ES2015 22.2.2.3 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE, ECMA_PROPERTY_FIXED) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ + +/* ES2015 22.2.2.1 */ +ROUTINE (LIT_MAGIC_STRING_FROM, ecma_builtin_typedarray_from, NON_FIXED, 1) + +/* ES2015 22.2.2.2 */ +ROUTINE (LIT_MAGIC_STRING_OF, ecma_builtin_typedarray_of, NON_FIXED, 0) + +/* ES2015 22.2.2.4 */ +ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_typedarray_species_get, ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.cpp new file mode 100644 index 00000000..691da4ba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint16array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint16array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint16arrayprototype ECMA Uint16Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.inc.h new file mode 100644 index 00000000..ec055f66 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint16Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT16ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.cpp new file mode 100644 index 00000000..18e5c6b3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint16array.inc.h" +#define BUILTIN_UNDERSCORED_ID uint16array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint16array ECMA Uint16Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint16array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT16_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint16array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint16Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint16array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT16_ARRAY); +} /* ecma_builtin_uint16array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.inc.h new file mode 100644 index 00000000..2c0af1f0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint16array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint16Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 2 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT16_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT16ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.cpp new file mode 100644 index 00000000..4b5e3842 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint32array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint32array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint32arrayprototype ECMA Uint32Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.inc.h new file mode 100644 index 00000000..a04098a3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint32Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT32ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.cpp new file mode 100644 index 00000000..cb495615 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint32array.inc.h" +#define BUILTIN_UNDERSCORED_ID uint32array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint32array ECMA Uint32Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint32array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint32array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint32Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint32array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT32_ARRAY); +} /* ecma_builtin_uint32array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.inc.h new file mode 100644 index 00000000..fd0389a4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint32array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint32Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 4 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT32_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT32ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.cpp new file mode 100644 index 00000000..8a8edb4a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8array-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8array_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8arrayprototype ECMA Uint8Array.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.inc.h new file mode 100644 index 00000000..07f94b0b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8Array prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8ARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.cpp new file mode 100644 index 00000000..5d20b7aa --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.cpp @@ -0,0 +1,77 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8array.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8array +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8array ECMA Uint8Array object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT8_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint8array_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint8Array + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT8_ARRAY); +} /* ecma_builtin_uint8array_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.inc.h new file mode 100644 index 00000000..d0259e9b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8array.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8Array description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT8_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8ARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.cpp new file mode 100644 index 00000000..534014b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.cpp @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8clampedarray-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8clampedarray_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8clampedarrayprototype ECMA Uint8ClampedArray.prototype object built-in + * @{ + */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.inc.h new file mode 100644 index 00000000..8564828a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.inc.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8ClampedArray prototype description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY +#include "ecma-builtin-typedarray-prototype-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.cpp new file mode 100644 index 00000000..9b348c24 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.cpp @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-typedarray-object.h" + +#include "jrt.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-uint8clampedarray.inc.h" +#define BUILTIN_UNDERSCORED_ID uint8clampedarray +#include "ecma-builtin-internal-routines-template.inc.h" +#include "ecma-builtin-typedarray-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup uint8clampedarray ECMA Uint8ClampedArray object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of Uint8ClampedArray + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8clampedarray_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_UINT8_CLAMPED_ARRAY_REQUIRES_NEW); +} /* ecma_builtin_uint8clampedarray_dispatch_call */ + +/** + * Handle calling [[Construct]] of Uint8ClampedArray + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_uint8clampedarray_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_typedarray_helper_dispatch_construct (arguments_list_p, arguments_list_len, ECMA_UINT8_CLAMPED_ARRAY); +} /* ecma_builtin_uint8clampedarray_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.inc.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.inc.h new file mode 100644 index 00000000..d3f0eb1f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Uint8ClampedArray description + */ + +#if JERRY_BUILTIN_TYPEDARRAY + +#define TYPEDARRAY_BYTES_PER_ELEMENT 1 +#define TYPEDARRAY_MAGIC_STRING_ID LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL +#define TYPEDARRAY_BUILTIN_ID ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY_PROTOTYPE +#include "ecma-builtin-typedarray-template.inc.h" + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/meson.build new file mode 100644 index 00000000..0f00f5c6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/builtin-objects/typedarray/meson.build @@ -0,0 +1,59 @@ +source_file = [ +'ecma-builtin-bigint64array-prototype.inc.h', +'ecma-builtin-bigint64array.inc.h', +'ecma-builtin-biguint64array-prototype.inc.h', +'ecma-builtin-biguint64array.inc.h', +'ecma-builtin-float32array-prototype.inc.h', +'ecma-builtin-float32array.inc.h', +'ecma-builtin-float64array-prototype.inc.h', +'ecma-builtin-float64array.inc.h', +'ecma-builtin-int16array-prototype.inc.h', +'ecma-builtin-int16array.inc.h', +'ecma-builtin-int32array-prototype.inc.h', +'ecma-builtin-int32array.inc.h', +'ecma-builtin-int8array-prototype.inc.h', +'ecma-builtin-int8array.inc.h', +'ecma-builtin-typedarray-helpers.h', +'ecma-builtin-typedarray-prototype-template.inc.h', +'ecma-builtin-typedarray-prototype.inc.h', +'ecma-builtin-typedarray-template.inc.h', +'ecma-builtin-typedarray.inc.h', +'ecma-builtin-uint16array-prototype.inc.h', +'ecma-builtin-uint16array.inc.h', +'ecma-builtin-uint32array-prototype.inc.h', +'ecma-builtin-uint32array.inc.h', +'ecma-builtin-uint8array-prototype.inc.h', +'ecma-builtin-uint8array.inc.h', +'ecma-builtin-uint8clampedarray-prototype.inc.h', +'ecma-builtin-uint8clampedarray.inc.h', +'ecma-builtin-bigint64array-prototype.cpp', +'ecma-builtin-bigint64array.cpp', +'ecma-builtin-biguint64array-prototype.cpp', +'ecma-builtin-biguint64array.cpp', +'ecma-builtin-float32array-prototype.cpp', +'ecma-builtin-float32array.cpp', +'ecma-builtin-float64array-prototype.cpp', +'ecma-builtin-float64array.cpp', +'ecma-builtin-int16array-prototype.cpp', +'ecma-builtin-int16array.cpp', +'ecma-builtin-int32array-prototype.cpp', +'ecma-builtin-int32array.cpp', +'ecma-builtin-int8array-prototype.cpp', +'ecma-builtin-int8array.cpp', +'ecma-builtin-typedarray-helpers.cpp', +'ecma-builtin-typedarray-prototype.cpp', +'ecma-builtin-typedarray.cpp', +'ecma-builtin-uint16array-prototype.cpp', +'ecma-builtin-uint16array.cpp', +'ecma-builtin-uint32array-prototype.cpp', +'ecma-builtin-uint32array.cpp', +'ecma-builtin-uint8array-prototype.cpp', +'ecma-builtin-uint8array.cpp', +'ecma-builtin-uint8clampedarray-prototype.cpp', +'ecma-builtin-uint8clampedarray.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/meson.build new file mode 100644 index 00000000..31e83fc9 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/meson.build @@ -0,0 +1,3 @@ +subdir('base') +subdir('builtin-objects') +subdir('operations') diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.cpp new file mode 100644 index 00000000..fd0c6798 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.cpp @@ -0,0 +1,461 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arguments-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaargumentsobject ECMA arguments object related routines + * @{ + */ + +/** + * Arguments object creation operation. + * + * See also: ECMA-262 v5, 10.6 + * + * @return ecma value of arguments object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shared context data */ + ecma_object_t *lex_env_p) /**< lexical environment the Arguments + * object is created for */ +{ + ecma_object_t *func_obj_p = shared_p->header.function_object_p; + const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p; + uint16_t formal_params_number; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + formal_params_number = ((cbc_uint16_arguments_t *) bytecode_data_p)->argument_end; + } + else + { + formal_params_number = ((cbc_uint8_arguments_t *) bytecode_data_p)->argument_end; + } + + uint32_t object_size = sizeof (ecma_unmapped_arguments_t); + uint32_t saved_arg_count = JERRY_MAX (shared_p->arg_list_len, formal_params_number); + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + object_size = sizeof (ecma_mapped_arguments_t); + } + + ecma_object_t *obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), + object_size + (saved_arg_count * sizeof (ecma_value_t)), + ECMA_OBJECT_TYPE_CLASS); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; + + arguments_p->header.u.cls.type = ECMA_OBJECT_CLASS_ARGUMENTS; + arguments_p->header.u.cls.u1.arguments_flags = ECMA_ARGUMENTS_OBJECT_NO_FLAGS; + arguments_p->header.u.cls.u2.formal_params_number = formal_params_number; + arguments_p->header.u.cls.u3.arguments_number = 0; + arguments_p->callee = ecma_make_object_value (func_obj_p); + + ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) obj_p) + object_size); + + for (uint32_t i = 0; i < shared_p->arg_list_len; i++) + { + argv_p[i] = ecma_copy_value_if_not_object (shared_p->arg_list_p[i]); + } + + for (uint32_t i = shared_p->arg_list_len; i < saved_arg_count; i++) + { + argv_p[i] = ECMA_VALUE_UNDEFINED; + } + + arguments_p->header.u.cls.u3.arguments_number = shared_p->arg_list_len; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) obj_p; + + ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->lex_env, lex_env_p); + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_MAPPED; + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE; + mapped_arguments_p->u.byte_code_p = (ecma_compiled_code_t *) bytecode_data_p; + } + else +#endif /* JERRY_SNAPSHOT_EXEC */ + { + ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->u.byte_code, bytecode_data_p); + } + + /* Static snapshots are not ref counted. */ + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) == 0) + { + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); + } + + ecma_value_t *formal_parameter_start_p; + formal_parameter_start_p = ecma_compiled_code_resolve_arguments_start ((ecma_compiled_code_t *) bytecode_data_p); + + for (uint32_t i = 0; i < formal_params_number; i++) + { + /* For legacy (non-strict) argument definition the trailing duplicated arguments cannot be lazy instantiated + E.g: function f (a,a,a,a) {} */ + if (JERRY_UNLIKELY (ecma_is_value_empty (formal_parameter_start_p[i]))) + { + ecma_property_value_t *prop_value_p; + ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); + + prop_value_p = + ecma_create_named_data_property (obj_p, prop_name_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + + ecma_deref_ecma_string (prop_name_p); + + prop_value_p->value = argv_p[i]; + argv_p[i] = ECMA_VALUE_EMPTY; + } + } + } + + return ecma_make_object_value (obj_p); +} /* ecma_op_create_arguments_object */ + +/** + * [[DefineOwnProperty]] ecma Arguments object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 10.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ + /* 3. */ + ecma_value_t ret_value = ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p); + + if (ECMA_IS_VALUE_ERROR (ret_value) + || !(((ecma_extended_object_t *) object_p)->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + return ret_value; + } + + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p; + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index >= mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number) + { + return ret_value; + } + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (ecma_is_value_empty (argv_p[index]) || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK) + { + return ret_value; + } + + if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; + return ret_value; + } + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + + ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p, name_p, property_desc_p->value, true); + + JERRY_ASSERT (ecma_is_value_empty (completion)); + } + + if ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; + } + + return ret_value; +} /* ecma_op_arguments_object_define_own_property */ + +/** + * Try to lazy instantiate the given property of a mapped/unmapped arguments object + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + ecma_property_value_t *prop_value_p; + ecma_property_t *prop_p; + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags; + + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (index >= arguments_number || ecma_is_value_empty (argv_p[index])) + { + return NULL; + } + + JERRY_ASSERT (argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK); + + prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE, + &prop_p); + + /* Passing the reference */ + prop_value_p->value = argv_p[index]; + + argv_p[index] = ECMA_VALUE_UNDEFINED; + return prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH) + && !(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) + { + prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_p); + + prop_value_p->value = ecma_make_uint32_value (arguments_number); + return prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE) + && !(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) + { + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_p); + + prop_value_p->value = arguments_p->callee; + } + else + { + ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); + + ecma_create_named_accessor_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE), + thrower_p, + thrower_p, + ECMA_PROPERTY_BUILT_IN_FIXED, + &prop_p); + } + return prop_p; + } + + if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR) + && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) + { + prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_p); + + prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT), + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES); + + JERRY_ASSERT (ecma_is_value_object (prop_value_p->value)); + ecma_deref_object (ecma_get_object_from_value (prop_value_p->value)); + return prop_p; + } + + return NULL; +} /* ecma_op_arguments_object_try_to_lazy_instantiate_property */ + +/** + * Delete configurable properties of arguments object + */ +void +ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED; + return; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)); + JERRY_ASSERT (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED; + return; + } + + if (ecma_prop_name_is_symbol (property_name_p)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)); + JERRY_ASSERT (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR)); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED; + return; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + } + + JERRY_ASSERT (argv_p[index] == ECMA_VALUE_UNDEFINED || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK); + + argv_p[index] = ECMA_VALUE_EMPTY; +} /* ecma_op_arguments_delete_built_in_property */ + +/** + * List names of an arguments object's lazy instantiated properties + */ +void +ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, /**< arguments object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; + + uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; + uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags; + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1); + } + + for (uint32_t index = 0; index < arguments_number; index++) + { + if (!ecma_is_value_empty (argv_p[index])) + { + ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); + ecma_collection_push_back (prop_names_p, ecma_make_string_value (index_string_p)); + prop_counter_p->array_index_named_props++; + } + } + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + if (!(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + + if (!(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLEE)); + prop_counter_p->string_named_props++; + } + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) + { + ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR); + ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (symbol_p)); + prop_counter_p->symbol_named_props++; + } +} /* ecma_op_arguments_object_list_lazy_property_names */ + +/** + * Get the formal parameter name corresponding to the given property index + * + * @return pointer to the formal parameter name + */ +ecma_string_t * +ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, /**< mapped arguments + * object */ + uint32_t index) /**< formal parameter index */ +{ + JERRY_ASSERT (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + JERRY_ASSERT (index < mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number); + + ecma_compiled_code_t *byte_code_p; + +#if JERRY_SNAPSHOT_EXEC + if (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE) + { + byte_code_p = mapped_arguments_p->u.byte_code_p; + } + else +#endif /* JERRY_SNAPSHOT_EXEC */ + { + byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code); + } + + ecma_value_t *formal_param_names_p = ecma_compiled_code_resolve_arguments_start (byte_code_p); + + return ecma_get_string_from_value (formal_param_names_p[index]); +} /* ecma_op_arguments_object_get_formal_parameter */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.h new file mode 100644 index 00000000..755b755c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arguments-object.h @@ -0,0 +1,42 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ARGUMENTS_OBJECT_H +#define ECMA_ARGUMENTS_OBJECT_H + +#include "ecma-globals.h" +#include "ecma-helpers.h" + +#include "vm-defines.h" + +ecma_value_t ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, ecma_object_t *lex_env_p); + +ecma_value_t ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); + +ecma_property_t *ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +void ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +void ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +ecma_string_t *ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, + uint32_t index); +#endif /* !ECMA_ARGUMENTS_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.cpp new file mode 100644 index 00000000..5da891d7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.cpp @@ -0,0 +1,1215 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-property-hashmap.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarrayobject ECMA Array object related routines + * @{ + */ + +/** + * Property name type flag for array indices. + */ +#define ECMA_FAST_ARRAY_UINT_DIRECT_STRING_PROP_TYPE (ECMA_DIRECT_STRING_UINT << ECMA_PROPERTY_NAME_TYPE_SHIFT) + +/** + * Allocate a new array object with the given length + * + * @return pointer to the constructed array object + */ +static ecma_object_t * +ecma_op_alloc_array_object (uint32_t length) /**< length of the new array */ +{ +#if JERRY_BUILTIN_ARRAY + ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); +#else /* !JERRY_BUILTIN_ARRAY */ + ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#endif /* JERRY_BUILTIN_ARRAY */ + + ecma_object_t *object_p = + ecma_create_object (array_prototype_object_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_ARRAY); + + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type. + * + * See also: ecma_object_get_class_name + */ + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length = length; + ext_obj_p->u.array.length_prop_and_hole_count = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_VIRTUAL; + + return object_p; +} /* ecma_op_alloc_array_object */ + +/** + * Check whether the given object is fast-access mode array + * + * @return true - if the object is fast-access mode array + * false, otherwise + */ +bool +ecma_op_object_is_fast_array (ecma_object_t *object_p) /**< ecma-object */ +{ + return (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY + && ecma_op_array_is_fast_array ((ecma_extended_object_t *) object_p)); +} /* ecma_op_object_is_fast_array */ + +/** + * Check whether the given array object is fast-access mode array + * + * @return true - if the array object is fast-access mode array + * false, otherwise + */ +bool +ecma_op_array_is_fast_array (ecma_extended_object_t *array_p) /**< ecma-array-object */ +{ + JERRY_ASSERT (ecma_get_object_base_type ((ecma_object_t *) array_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + + return array_p->u.array.length_prop_and_hole_count & ECMA_FAST_ARRAY_FLAG; +} /* ecma_op_array_is_fast_array */ + +/** + * Allocate a new array object with the given length + * + * Note: The returned array can be normal of fast access mode + * + * @return pointer to the constructed array object + */ +ecma_object_t * +ecma_op_new_array_object (uint32_t length) /**< length of the new array */ +{ + ecma_object_t *object_p = ecma_op_alloc_array_object (length); + + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length); + ecma_value_t *values_p = NULL; + + if (length > 0) + { + if (length >= ECMA_FAST_ARRAY_MAX_HOLE_COUNT) + { + return object_p; + } + + values_p = (ecma_value_t *) jmem_heap_alloc_block_null_on_error (aligned_length * sizeof (ecma_value_t)); + + if (JERRY_UNLIKELY (values_p == NULL)) + { + return object_p; + } + } + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; + ext_obj_p->u.array.length_prop_and_hole_count += length * ECMA_FAST_ARRAY_HOLE_ONE; + + for (uint32_t i = 0; i < aligned_length; i++) + { + values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); + ECMA_SET_POINTER (object_p->u1.property_list_cp, values_p); + return object_p; +} /* ecma_op_new_array_object */ + +/** + * Allocate a new array object from the given length + * + * Note: The returned array can be normal of fast access mode + * + * @return NULL - if the given length is invalid + * pointer to the constructed array object - otherwise + */ +ecma_object_t * +ecma_op_new_array_object_from_length (ecma_length_t length) /**< length of the new array */ +{ + if (length > UINT32_MAX) + { + ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + return NULL; + } + + return ecma_op_new_array_object ((uint32_t) length); +} /* ecma_op_new_array_object_from_length */ + +/** + * Allocate a new array object from the given buffer + * + * Note: The returned array can be normal of fast access mode + * + * @return ecma_value - constructed array object + */ +ecma_value_t +ecma_op_new_array_object_from_buffer (const ecma_value_t *args_p, /**< array element list */ + uint32_t length) /**< number of array elements */ +{ + if (length == 0) + { + return ecma_make_object_value (ecma_op_new_array_object (0)); + } + + ecma_object_t *object_p = ecma_op_alloc_array_object (length); + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length); + ecma_value_t *values_p; + values_p = (ecma_value_t *) jmem_heap_alloc_block_null_on_error (aligned_length * sizeof (ecma_value_t)); + + if (values_p != NULL) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; + JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); + + for (uint32_t i = 0; i < length; i++) + { + JERRY_ASSERT (!ecma_is_value_array_hole (args_p[i])); + values_p[i] = ecma_copy_value_if_not_object (args_p[i]); + } + + for (uint32_t i = length; i < aligned_length; i++) + { + values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + ECMA_SET_POINTER (object_p->u1.property_list_cp, values_p); + } + else + { + for (uint32_t i = 0; i < length; i++) + { + JERRY_ASSERT (!ecma_is_value_array_hole (args_p[i])); + + ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); + ecma_property_value_t *prop_value_p; + prop_value_p = + ecma_create_named_data_property (object_p, prop_name_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + ecma_deref_ecma_string (prop_name_p); + prop_value_p->value = ecma_copy_value_if_not_object (args_p[i]); + } + } + + return ecma_make_object_value (object_p); +} /* ecma_op_new_array_object_from_buffer */ + +/** + * Allocate a new fast acces mode array object from the given collection + * + * Note: The given collection will be unavailable after and it's underlying buffer is reused + * + * @return ecma_value - constructed fast access mode array object + */ +ecma_value_t +ecma_op_new_array_object_from_collection (ecma_collection_t *collection_p, /**< collection to create array from */ + bool unref_objects) /**< true - if the collection potentially + containts objects + false - otherwise */ +{ + const uint32_t item_count = collection_p->item_count; + + if (item_count == 0) + { + ecma_collection_destroy (collection_p); + return ecma_make_object_value (ecma_op_new_array_object (0)); + } + + ecma_object_t *object_p; + ecma_value_t *buffer_p = collection_p->buffer_p; + const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity); + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (collection_p->item_count); + + jmem_heap_free_block (collection_p, sizeof (ecma_collection_t)); + buffer_p = (ecma_value_t *) jmem_heap_realloc_block (buffer_p, old_size, aligned_length * sizeof (ecma_value_t)); + object_p = (ecma_object_t *) ecma_op_alloc_array_object (item_count); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; + JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); + JERRY_ASSERT (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE); + ECMA_SET_POINTER (object_p->u1.property_list_cp, buffer_p); + + if (JERRY_UNLIKELY (unref_objects)) + { + for (uint32_t i = 0; i < item_count; i++) + { + /* Strong references from the collection are no longer needed + since GC will mark these object as a fast access mode array properties */ + ecma_deref_if_object (buffer_p[i]); + } + } + + for (uint32_t i = item_count; i < aligned_length; i++) + { + buffer_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + return ecma_make_object_value (object_p); +} /* ecma_op_new_array_object_from_collection */ + +/** + * Converts a fast access mode array back to a normal property list based array + */ +void +ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mode array object */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + if (object_p->u1.property_list_cp == JMEM_CP_NULL) + { + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_FAST_ARRAY_FLAG; + return; + } + + uint32_t length = ext_obj_p->u.array.length; + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length); + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + ecma_ref_object (object_p); + + ecma_property_pair_t *property_pair_p = NULL; + jmem_cpointer_t next_property_pair_cp = JMEM_CP_NULL; + + uint32_t prop_index = 1; + int32_t index = (int32_t) (length - 1); + + while (index >= 0) + { + if (ecma_is_value_array_hole (values_p[index])) + { + index--; + continue; + } + + if (prop_index == 1) + { + property_pair_p = ecma_alloc_property_pair (); + property_pair_p->header.next_property_cp = next_property_pair_cp; + property_pair_p->names_cp[0] = LIT_INTERNAL_MAGIC_STRING_DELETED; + property_pair_p->header.types[0] = ECMA_PROPERTY_TYPE_DELETED; + ECMA_SET_NON_NULL_POINTER (next_property_pair_cp, property_pair_p); + } + + JERRY_ASSERT (index <= ECMA_DIRECT_STRING_MAX_IMM); + + property_pair_p->names_cp[prop_index] = (jmem_cpointer_t) index; + property_pair_p->header.types[prop_index] = + (ecma_property_t) (ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE + | ECMA_FAST_ARRAY_UINT_DIRECT_STRING_PROP_TYPE); + + property_pair_p->values[prop_index].value = values_p[index]; + + index--; + prop_index = !prop_index; + } + + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_FAST_ARRAY_FLAG; + jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t)); + ECMA_SET_POINTER (object_p->u1.property_list_cp, property_pair_p); + + ecma_deref_object (object_p); +} /* ecma_fast_array_convert_to_normal */ + +/** + * [[Put]] operation for a fast access mode array + * + * @return false - If the property name is not array index, or the requested index to be set + * would result too much array hole in the underlying buffer. The these cases + * the array is converted back to normal property list based array. + * true - If the indexed property can be set with/without resizing the underlying buffer. + */ +bool +ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode array object */ + uint32_t index, /**< property name index */ + ecma_value_t value) /**< value to be set */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t old_length = ext_obj_p->u.array.length; + + ecma_value_t *values_p; + + if (JERRY_LIKELY (index < old_length)) + { + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (ecma_is_value_array_hole (values_p[index])) + { + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + } + else + { + ecma_free_value_if_not_object (values_p[index]); + } + + values_p[index] = ecma_copy_value_if_not_object (value); + + return true; + } + + uint32_t old_holes = ext_obj_p->u.array.length_prop_and_hole_count; + uint32_t new_holes = index - old_length; + + if (JERRY_UNLIKELY (new_holes > (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - (old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT)))) + { + ecma_fast_array_convert_to_normal (object_p); + + return false; + } + + uint32_t new_length = index + 1; + + JERRY_ASSERT (new_length < UINT32_MAX); + + const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length); + + if (JERRY_LIKELY (index < aligned_length)) + { + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + /* This area is filled with ECMA_VALUE_ARRAY_HOLE, but not counted in u.array.length_prop_and_hole_count */ + JERRY_ASSERT (ecma_is_value_array_hole (values_p[index])); + ext_obj_p->u.array.length_prop_and_hole_count += new_holes * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length = new_length; + } + else + { + values_p = ecma_fast_array_extend (object_p, new_length); + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + } + + values_p[index] = ecma_copy_value_if_not_object (value); + + return true; +} /* ecma_fast_array_set_property */ + +/** + * Get the number of array holes in a fast access array object + * + * @return number of array holes in a fast access array object + */ +uint32_t +ecma_fast_array_get_hole_count (ecma_object_t *obj_p) /**< fast access mode array object */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (obj_p)); + + return ((ecma_extended_object_t *) obj_p)->u.array.length_prop_and_hole_count >> ECMA_FAST_ARRAY_HOLE_SHIFT; +} /* ecma_fast_array_get_hole_count */ + +/** + * Extend the underlying buffer of a fast mode access array for the given new length + * + * @return pointer to the extended underlying buffer + */ +ecma_value_t * +ecma_fast_array_extend (ecma_object_t *object_p, /**< fast access mode array object */ + uint32_t new_length) /**< new length of the fast access mode array */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t old_length = ext_obj_p->u.array.length; + + JERRY_ASSERT (old_length < new_length); + + ecma_ref_object (object_p); + + ecma_value_t *new_values_p; + const uint32_t old_length_aligned = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length); + const uint32_t new_length_aligned = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length); + + if (object_p->u1.property_list_cp == JMEM_CP_NULL) + { + new_values_p = (ecma_value_t *) jmem_heap_alloc_block (new_length_aligned * sizeof (ecma_value_t)); + } + else + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p, + old_length_aligned * sizeof (ecma_value_t), + new_length_aligned * sizeof (ecma_value_t)); + } + + for (uint32_t i = old_length; i < new_length_aligned; i++) + { + new_values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + ext_obj_p->u.array.length_prop_and_hole_count += (new_length - old_length) * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length = new_length; + + ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, new_values_p); + + ecma_deref_object (object_p); + return new_values_p; +} /* ecma_fast_array_extend */ + +/** + * Delete the array object's property referenced by its value pointer. + * + * Note: specified property must be owned by specified object. + * + * @return true, if the property is deleted + * false, otherwise + */ +bool +ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + if (!ecma_op_object_is_fast_array (object_p)) + { + return false; + } + + JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + + uint32_t index = ecma_string_get_array_index (property_name_p); + + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + JERRY_ASSERT (index < ext_obj_p->u.array.length); + + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (ecma_is_value_array_hole (values_p[index])) + { + return true; + } + + ecma_free_value_if_not_object (values_p[index]); + + values_p[index] = ECMA_VALUE_ARRAY_HOLE; + ext_obj_p->u.array.length_prop_and_hole_count += ECMA_FAST_ARRAY_HOLE_ONE; + return true; +} /* ecma_array_object_delete_property */ + +/** + * Low level delete of fast access mode array items + * + * @return the updated value of new_length + */ +uint32_t +ecma_delete_fast_array_properties (ecma_object_t *object_p, /**< fast access mode array */ + uint32_t new_length) /**< new length of the fast access mode array */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + + ecma_ref_object (object_p); + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + uint32_t old_length = ext_obj_p->u.array.length; + const uint32_t old_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length); + JERRY_ASSERT (new_length < old_length); + + for (uint32_t i = new_length; i < old_length; i++) + { + if (ecma_is_value_array_hole (values_p[i])) + { + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + } + else + { + ecma_free_value_if_not_object (values_p[i]); + } + } + + jmem_cpointer_t new_property_list_cp; + + if (new_length == 0) + { + jmem_heap_free_block (values_p, old_aligned_length * sizeof (ecma_value_t)); + new_property_list_cp = JMEM_CP_NULL; + } + else + { + const uint32_t new_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length); + + ecma_value_t *new_values_p; + new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p, + old_aligned_length * sizeof (ecma_value_t), + new_aligned_length * sizeof (ecma_value_t)); + + for (uint32_t i = new_length; i < new_aligned_length; i++) + { + new_values_p[i] = ECMA_VALUE_ARRAY_HOLE; + } + + ECMA_SET_NON_NULL_POINTER (new_property_list_cp, new_values_p); + } + + ext_obj_p->u.array.length = new_length; + object_p->u1.property_list_cp = new_property_list_cp; + + ecma_deref_object (object_p); + + return new_length; +} /* ecma_delete_fast_array_properties */ + +/** + * Update the length of a fast access mode array to a new length + * + * Note: if the new length would result too much array hole in the underlying arraybuffer + * the array is converted back to normal property list based array + */ +static void +ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array object */ + uint32_t new_length) /**< new length of the fast access mode array object*/ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t old_length = ext_obj_p->u.array.length; + + JERRY_ASSERT (new_length >= old_length); + + if (new_length == old_length) + { + return; + } + + uint32_t old_holes = ext_obj_p->u.array.length_prop_and_hole_count; + uint32_t new_holes = new_length - old_length; + + if (JERRY_UNLIKELY (new_holes > (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - (old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT)))) + { + ecma_fast_array_convert_to_normal (object_p); + } + else + { + ecma_fast_array_extend (object_p, new_length); + } +} /* ecma_fast_array_set_length */ + +/** + * Get collection of property names of a fast access mode array object + * + * Note: Since the fast array object only contains indexed, enumerable, writable, configurable properties + * we can return a collection of non-array hole array indices + * + * @return collection of strings - property names + */ +ecma_collection_t * +ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, /**< fast access mode array object */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_collection_t *ret_p = ecma_new_collection (); + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t length = ext_obj_p->u.array.length; + + if (length != 0) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < length; i++) + { + if (ecma_is_value_array_hole (values_p[i])) + { + continue; + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i); + + ecma_collection_push_back (ret_p, ecma_make_string_value (index_str_p)); + } + } + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + } + + return ret_p; +} /* ecma_fast_array_object_own_property_keys */ + +/** + * Array object creation with custom prototype. + * + * See also: ECMA-262 v6, 9.4.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_object_t * +ecma_op_array_species_create (ecma_object_t *original_array_p, /**< The object from whom the new array object + * is being created */ + ecma_length_t length) /**< length of the array */ +{ + ecma_value_t constructor = ECMA_VALUE_UNDEFINED; + ecma_value_t original_array = ecma_make_object_value (original_array_p); + + ecma_value_t is_array = ecma_is_value_array (original_array); + + if (ECMA_IS_VALUE_ERROR (is_array)) + { + return NULL; + } + + if (ecma_is_value_true (is_array)) + { + constructor = ecma_op_object_get_by_magic_id (original_array_p, LIT_MAGIC_STRING_CONSTRUCTOR); + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return NULL; + } + +#if JERRY_BUILTIN_REALMS + if (ecma_is_constructor (constructor)) + { + ecma_object_t *constructor_p = ecma_get_object_from_value (constructor); + ecma_global_object_t *global_object_p = ecma_op_function_get_function_realm (constructor_p); + + if ((ecma_object_t *) global_object_p != ecma_builtin_get_global () + && constructor_p == ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_ARRAY)) + { + ecma_deref_object (constructor_p); + constructor = ECMA_VALUE_UNDEFINED; + } + } +#endif /* JERRY_BUILTIN_REALMS */ + + if (ecma_is_value_object (constructor)) + { + ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); + constructor = ecma_op_object_get_by_symbol_id (ctor_object_p, LIT_GLOBAL_SYMBOL_SPECIES); + ecma_deref_object (ctor_object_p); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return NULL; + } + + if (ecma_is_value_null (constructor)) + { + constructor = ECMA_VALUE_UNDEFINED; + } + } + } + + if (ecma_is_value_undefined (constructor)) + { + return ecma_op_new_array_object_from_length (length); + } + + if (!ecma_is_constructor (constructor)) + { + ecma_free_value (constructor); + ecma_raise_type_error (ECMA_ERR_INVALID_SPECIES_CONSTRUCTOR); + return NULL; + } + + ecma_value_t len_val = ecma_make_length_value (length); + ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); + ecma_value_t ret_val = ecma_op_function_construct (ctor_object_p, ctor_object_p, &len_val, 1); + + ecma_deref_object (ctor_object_p); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + return NULL; + } + + return ecma_get_object_from_value (ret_val); +} /* ecma_op_array_species_create */ + +/** + * CreateArrayIterator Abstract Operation + * + * See also: + * ECMA-262 v6, 22.1.5.1 + * + * Referenced by: + * ECMA-262 v6, 22.1.3.4 + * ECMA-262 v6, 22.1.3.13 + * ECMA-262 v6, 22.1.3.29 + * ECMA-262 v6, 22.1.3.30 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return array iterator object + */ +ecma_value_t +ecma_op_create_array_iterator (ecma_object_t *obj_p, /**< array object */ + ecma_iterator_kind_t kind) /**< array iterator kind */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE); + + return ecma_op_create_iterator_object (ecma_make_object_value (obj_p), + prototype_obj_p, + ECMA_OBJECT_CLASS_ARRAY_ITERATOR, + kind); +} /* ecma_op_create_array_iterator */ + +/** + * Low level delete of array items from new_length to old_length + * + * Note: new_length must be less than old_length + * + * @return the updated value of new_length + */ +static uint32_t +ecma_delete_array_properties (ecma_object_t *object_p, /**< object */ + uint32_t new_length, /**< new length */ + uint32_t old_length) /**< old length */ +{ + JERRY_ASSERT (new_length < old_length); + JERRY_ASSERT (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + + if (ecma_op_object_is_fast_array (object_p)) + { + return ecma_delete_fast_array_properties (object_p, new_length); + } + + /* First the minimum value of new_length is updated. */ + jmem_cpointer_t current_prop_cp = object_p->u1.property_list_cp; + + if (current_prop_cp == JMEM_CP_NULL) + { + return new_length; + } + + ecma_property_header_t *current_prop_p; + +#if JERRY_PROPERTY_HASHMAP + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + + if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + current_prop_cp = current_prop_p->next_property_cp; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (current_prop_cp != JMEM_CP_NULL) + { + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (current_prop_p->types[i] != ECMA_PROPERTY_TYPE_DELETED + && !ecma_is_property_configurable (current_prop_p->types[i])) + { + uint32_t index = ecma_string_get_property_index (current_prop_p->types[i], prop_pair_p->names_cp[i]); + + if (index < old_length && index >= new_length) + { + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + + new_length = index + 1; + + if (new_length == old_length) + { + /* Early return. */ + return new_length; + } + } + } + } + + current_prop_cp = current_prop_p->next_property_cp; + } + + /* Second all properties between new_length and old_length are deleted. */ + current_prop_cp = object_p->u1.property_list_cp; + ecma_property_header_t *prev_prop_p = NULL; + +#if JERRY_PROPERTY_HASHMAP + JERRY_ASSERT (current_prop_cp != JMEM_CP_NULL); + + ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP; + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + + if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prev_prop_p = current_prop_p; + current_prop_cp = current_prop_p->next_property_cp; + hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (current_prop_cp != JMEM_CP_NULL) + { + current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp); + + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p)); + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p; + + for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (current_prop_p->types[i] != ECMA_PROPERTY_TYPE_DELETED + && ecma_is_property_configurable (current_prop_p->types[i])) + { + uint32_t index = ecma_string_get_property_index (current_prop_p->types[i], prop_pair_p->names_cp[i]); + + if (index < old_length && index >= new_length) + { + JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP) + { + hashmap_status = + ecma_property_hashmap_delete (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + ecma_gc_free_property (object_p, prop_pair_p, i); + current_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED; + prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED; + } + } + } + + if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_DELETED + && current_prop_p->types[1] == ECMA_PROPERTY_TYPE_DELETED) + { + if (prev_prop_p == NULL) + { + object_p->u1.property_list_cp = current_prop_p->next_property_cp; + } + else + { + prev_prop_p->next_property_cp = current_prop_p->next_property_cp; + } + + jmem_cpointer_t next_prop_cp = current_prop_p->next_property_cp; + ecma_dealloc_property_pair ((ecma_property_pair_t *) current_prop_p); + current_prop_cp = next_prop_cp; + } + else + { + prev_prop_p = current_prop_p; + current_prop_cp = current_prop_p->next_property_cp; + } + } + +#if JERRY_PROPERTY_HASHMAP + if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) + { + ecma_property_hashmap_free (object_p); + ecma_property_hashmap_create (object_p); + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + return new_length; +} /* ecma_delete_array_properties */ + +/** + * Update the length of an array to a new length + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */ + ecma_value_t new_value, /**< new length value */ + uint16_t flags) /**< property descriptor flags */ +{ + ecma_number_t new_len_num; + ecma_value_t completion = ecma_op_to_number (new_value, &new_len_num); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion)); + + if (ecma_is_value_object (new_value)) + { + ecma_value_t compared_num_val = ecma_op_to_number (new_value, &new_len_num); + + if (ECMA_IS_VALUE_ERROR (compared_num_val)) + { + return compared_num_val; + } + } + + uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); + + if (((ecma_number_t) new_len_uint32) != new_len_num) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAY_LENGTH); + } + + /* Only the writable and data properties can be modified. */ + if (flags + & (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + uint32_t old_len_uint32 = ext_object_p->u.array.length; + + if (new_len_num == old_len_uint32) + { + /* Only the writable flag must be updated. */ + if (flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + if (!(flags & JERRY_PROP_IS_WRITABLE)) + { + if (ecma_op_array_is_fast_array (ext_object_p)) + { + ecma_fast_array_convert_to_normal (object_p); + } + + ext_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; + } + else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); + } + } + return ECMA_VALUE_TRUE; + } + else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); + } + + uint32_t current_len_uint32 = new_len_uint32; + + if (new_len_uint32 < old_len_uint32) + { + current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32); + } + else if (ecma_op_object_is_fast_array (object_p)) + { + ecma_fast_array_set_length (object_p, new_len_uint32); + } + + ext_object_p->u.array.length = current_len_uint32; + + if ((flags & JERRY_PROP_IS_WRITABLE_DEFINED) && !(flags & JERRY_PROP_IS_WRITABLE)) + { + if (ecma_op_array_is_fast_array (ext_object_p)) + { + ecma_fast_array_convert_to_normal (object_p); + } + + ext_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; + } + + if (current_len_uint32 == new_len_uint32) + { + return ECMA_VALUE_TRUE; + } + + return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); +} /* ecma_op_array_object_set_length */ + +/** + * Property descriptor bitset for fast array data properties. + * If the property desciptor fields contains all the flags below + * attempt to stay fast access array during [[DefineOwnProperty]] operation. + */ +#define ECMA_FAST_ARRAY_DATA_PROP_FLAGS \ + (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE \ + | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_WRITABLE_DEFINED \ + | JERRY_PROP_IS_WRITABLE) + +/** + * [[DefineOwnProperty]] ecma array object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 15.4.5.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the array object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ +{ + if (ecma_string_is_length (property_name_p)) + { + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + return ecma_op_array_object_set_length (object_p, property_desc_p->value, property_desc_p->flags); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ecma_value_t length_value = ecma_make_uint32_value (ext_object_p->u.array.length); + + ecma_value_t result = ecma_op_array_object_set_length (object_p, length_value, property_desc_p->flags); + + ecma_fast_free_value (length_value); + return result; + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_op_object_is_fast_array (object_p)) + { + if ((property_desc_p->flags & ECMA_FAST_ARRAY_DATA_PROP_FLAGS) == ECMA_FAST_ARRAY_DATA_PROP_FLAGS) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) + { + ecma_fast_array_convert_to_normal (object_p); + } + else if (ecma_fast_array_set_property (object_p, index, property_desc_p->value)) + { + return ECMA_VALUE_TRUE; + } + + JERRY_ASSERT (!ecma_op_array_is_fast_array (ext_object_p)); + } + else + { + ecma_fast_array_convert_to_normal (object_p); + } + } + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p); + } + + bool update_length = (index >= ext_object_p->u.array.length); + + if (update_length && !ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_property_descriptor_t prop_desc; + + prop_desc = *property_desc_p; + prop_desc.flags &= (uint16_t) ~JERRY_PROP_SHOULD_THROW; + + ecma_value_t completition = ecma_op_general_object_define_own_property (object_p, property_name_p, &prop_desc); + JERRY_ASSERT (ecma_is_value_boolean (completition)); + + if (ecma_is_value_false (completition)) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + if (update_length) + { + ext_object_p->u.array.length = index + 1; + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_array_object_define_own_property */ + +/** + * Get the length of the an array object + * + * @return the array length + */ +uint32_t +ecma_array_get_length (ecma_object_t *array_p) /**< array object */ +{ + JERRY_ASSERT (ecma_get_object_base_type (array_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); + + return ((ecma_extended_object_t *) array_p)->u.array.length; +} /* ecma_array_get_length */ + +/** + * The Array.prototype and %TypedArray%.prototype objects' 'toString' routine. + * + * See also: + * ECMA-262 v5, 15.4.4.2 + * ECMA-262 v6, 22.1.3.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_array_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + JERRY_ASSERT (ecma_is_value_object (this_arg)); + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); + + /* 2. */ + ecma_value_t join_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_JOIN); + if (ECMA_IS_VALUE_ERROR (join_value)) + { + return join_value; + } + + if (!ecma_op_is_callable (join_value)) + { + /* 3. */ + ret_value = ecma_builtin_helper_object_to_string (this_arg); + } + else + { + /* 4. */ + ecma_object_t *join_func_obj_p = ecma_get_object_from_value (join_value); + + ret_value = ecma_op_function_call (join_func_obj_p, this_arg, NULL, 0); + } + + ecma_free_value (join_value); + + return ret_value; +} /* ecma_array_object_to_string */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.h new file mode 100644 index 00000000..73d65805 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-array-object.h @@ -0,0 +1,110 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ARRAY_OBJECT_H +#define ECMA_ARRAY_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarrayobject ECMA Array object related routines + * @{ + */ + +/** + * Attributes of fast access mode arrays: + * + * - The internal property is replaced with a buffer which directly stores the values + * - Whenever any operation would change the following attributes of the array it should be converted back to normal + * - All properties must be enumerable configurable writable data properties + * - The prototype must be Array.prototype + * - [[Extensible]] internal property must be true + * - 'length' property of the array must be writable + * + * - The conversion is also required when a property is set if: + * - The property name is not an array index + * - The new hole count of the array would reach ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT + */ + +/** + * Maximum number of new array holes in a fast mode access array. + * If the number of new holes exceeds this limit, the array is converted back + * to normal property list based array. + */ +#define ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT 32 + +/** + * Bitshift index for fast array hole count representation + */ +#define ECMA_FAST_ARRAY_HOLE_SHIFT 8 + +/** + * This number represents 1 array hole in underlying buffer of a fast acces mode array + */ +#define ECMA_FAST_ARRAY_HOLE_ONE (1 << ECMA_FAST_ARRAY_HOLE_SHIFT) + +/** + * Maximum number of array holes in a fast access mode array + */ +#define ECMA_FAST_ARRAY_MAX_HOLE_COUNT (1 << 16) + +ecma_object_t *ecma_op_new_array_object (uint32_t length); + +ecma_object_t *ecma_op_new_array_object_from_length (ecma_length_t length); + +ecma_value_t ecma_op_new_array_object_from_buffer (const ecma_value_t *args_p, uint32_t length); + +ecma_value_t ecma_op_new_array_object_from_collection (ecma_collection_t *collection_p, bool unref_objects); + +bool ecma_op_object_is_fast_array (ecma_object_t *object_p); + +bool ecma_op_array_is_fast_array (ecma_extended_object_t *array_p); + +uint32_t ecma_fast_array_get_hole_count (ecma_object_t *obj_p); + +ecma_value_t *ecma_fast_array_extend (ecma_object_t *object_p, uint32_t new_lengt); + +bool ecma_fast_array_set_property (ecma_object_t *object_p, uint32_t index, ecma_value_t value); + +bool ecma_array_object_delete_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +uint32_t ecma_delete_fast_array_properties (ecma_object_t *object_p, uint32_t new_length); + +ecma_collection_t *ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, jerry_property_filter_t filter); + +void ecma_fast_array_convert_to_normal (ecma_object_t *object_p); + +ecma_object_t *ecma_op_array_species_create (ecma_object_t *original_array_p, ecma_length_t length); + +ecma_value_t ecma_op_create_array_iterator (ecma_object_t *obj_p, ecma_iterator_kind_t kind); + +ecma_value_t ecma_op_array_object_set_length (ecma_object_t *object_p, ecma_value_t new_value, uint16_t flags); + +ecma_value_t ecma_op_array_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); + +uint32_t ecma_array_get_length (ecma_object_t *array_p); + +ecma_value_t ecma_array_object_to_string (ecma_value_t this_arg); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ARRAY_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.cpp new file mode 100644 index 00000000..be61d7cd --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.cpp @@ -0,0 +1,562 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarraybufferobject ECMA ArrayBuffer object related routines + * @{ + */ + +/** + * Creating ArrayBuffer objects with a buffer after the arraybuffer header + * + * @return new ArrayBuffer object + */ +ecma_object_t * +ecma_arraybuffer_create_object (uint8_t type, /**< type of the arraybuffer */ + uint32_t length) /**< length of the arraybuffer */ +{ + ecma_builtin_id_t prototype_id; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER || type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER); + + prototype_id = (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER ? ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE + : ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER); + + prototype_id = ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + ecma_object_t *object_p = ecma_create_object (ecma_builtin_get (prototype_id), + sizeof (ecma_extended_object_t) + length, + ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = type; + ext_object_p->u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_ALLOCATED; + ext_object_p->u.cls.u3.length = length; + + memset ((uint8_t *) (ext_object_p + 1), 0, length); + return object_p; +} /* ecma_arraybuffer_create_object */ + +/** + * Creating ArrayBuffer objects with a pointer to its buffer + * + * @return new ArrayBuffer object + */ +ecma_object_t * +ecma_arraybuffer_create_object_with_buffer (uint8_t type, /**< type of the arraybuffer */ + uint32_t length) +{ + ecma_builtin_id_t prototype_id; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER || type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER); + + prototype_id = (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER ? ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE + : ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER); + + prototype_id = ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + ecma_object_t *object_p = + ecma_create_object (ecma_builtin_get (prototype_id), sizeof (ecma_arraybuffer_pointer_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p; + arraybuffer_pointer_p->extended_object.u.cls.type = type; + arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_HAS_POINTER; + arraybuffer_pointer_p->extended_object.u.cls.u3.length = length; + + arraybuffer_pointer_p->buffer_p = NULL; + arraybuffer_pointer_p->arraybuffer_user_p = NULL; + + return object_p; +} /* ecma_arraybuffer_create_object_with_buffer */ + +/** + * Creating ArrayBuffer objects based on the array length + * + * @return new ArrayBuffer object + */ +ecma_object_t * +ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */ +{ + if (length > JERRY_CONTEXT (arraybuffer_compact_allocation_limit)) + { + return ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_ARRAY_BUFFER, length); + } + + return ecma_arraybuffer_create_object (ECMA_OBJECT_CLASS_ARRAY_BUFFER, length); +} /* ecma_arraybuffer_new_object */ + +/** + * Allocate a backing store for an array buffer. + * + * @return buffer pointer on success, + * NULL otherwise + */ +ecma_value_t +ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */ +{ + JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)); + + ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) arraybuffer_p; + + if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED) + { + extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + return ECMA_VALUE_UNDEFINED; + } + + uint32_t arraybuffer_length = extended_object_p->u.cls.u3.length; + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p; + jerry_arraybuffer_allocate_cb_t arraybuffer_allocate_callback = JERRY_CONTEXT (arraybuffer_allocate_callback); + uint8_t *buffer_p; + + if (arraybuffer_allocate_callback != NULL) + { + jerry_arraybuffer_type_t type = JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + if (extended_object_p->u.cls.type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER) + { + type = JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER; + } +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + buffer_p = arraybuffer_allocate_callback (type, + arraybuffer_length, + &arraybuffer_pointer_p->arraybuffer_user_p, + JERRY_CONTEXT (arraybuffer_allocate_callback_user_p)); + } + else + { + buffer_p = (uint8_t *) jmem_heap_alloc_block_null_on_error (arraybuffer_length); + } + + if (buffer_p == NULL) + { + return ecma_raise_range_error (ECMA_ERR_ALLOCATE_ARRAY_BUFFER); + } + + arraybuffer_pointer_p->buffer_p = buffer_p; + extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED; + + memset (buffer_p, 0, arraybuffer_length); + return ECMA_VALUE_UNDEFINED; +} /* ecma_arraybuffer_allocate_buffer */ + +/** + * Allocate a backing store for an array buffer, throws an error if the allocation fails. + * + * @return ECMA_VALUE_UNDEFINED on success, + * ECMA_VALUE_ERROR otherwise + */ +ecma_value_t +ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p) +{ + JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)); + + return ecma_arraybuffer_allocate_buffer (arraybuffer_p); +} /* ecma_arraybuffer_allocate_buffer_throw */ + +/** + * Release the backing store allocated by an array buffer. + */ +void +ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (arraybuffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (arraybuffer_p)); + + jerry_arraybuffer_free_cb_t free_callback = JERRY_CONTEXT (arraybuffer_free_callback); + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p; + + if (arraybuffer_pointer_p->buffer_p == NULL) + { + return; + } + + uint32_t arraybuffer_length = arraybuffer_pointer_p->extended_object.u.cls.u3.length; + + if (free_callback == NULL) + { + jmem_heap_free_block (arraybuffer_pointer_p->buffer_p, arraybuffer_length); + return; + } + + jerry_arraybuffer_type_t type = JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER; + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + if (arraybuffer_pointer_p->extended_object.u.cls.type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER) + { + type = JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER; + } +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + + free_callback (type, + (uint8_t*) arraybuffer_pointer_p->buffer_p, + arraybuffer_length, + arraybuffer_pointer_p->arraybuffer_user_p, + JERRY_CONTEXT (arraybuffer_allocate_callback_user_p)); +} /* ecma_arraybuffer_release_buffer */ + +/** + * ArrayBuffer object creation operation. + * + * See also: ES2015 24.1.1.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that + * are passed to String constructor */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t length_num = 0; + + if (arguments_list_len > 0) + { + if (ecma_is_value_number (arguments_list_p[0])) + { + length_num = ecma_get_number_from_value (arguments_list_p[0]); + } + else + { + ecma_value_t to_number_value = ecma_op_to_number (arguments_list_p[0], &length_num); + + if (ECMA_IS_VALUE_ERROR (to_number_value)) + { + ecma_deref_object (proto_p); + return to_number_value; + } + } + + if (ecma_number_is_nan (length_num)) + { + length_num = 0; + } + + const uint32_t maximum_size_in_byte = UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1; + + if (length_num <= -1.0 || length_num > (ecma_number_t) maximum_size_in_byte + 0.5) + { + ecma_deref_object (proto_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_ARRAYBUFFER_LENGTH); + } + } + + uint32_t length_uint32 = ecma_number_to_uint32 (length_num); + + ecma_object_t *array_buffer = ecma_arraybuffer_new_object (length_uint32); + ECMA_SET_NON_NULL_POINTER (array_buffer->u2.prototype_cp, proto_p); + ecma_deref_object (proto_p); + + return ecma_make_object_value (array_buffer); +} /* ecma_op_create_arraybuffer_object */ + +/** + * Helper function: check if the target is ArrayBuffer + * + * + * See also: ES2015 24.1.1.4 + * + * @return true - if value is an ArrayBuffer object + * false - otherwise + */ +bool +ecma_is_arraybuffer (ecma_value_t target) /**< the target value */ +{ + return (ecma_is_value_object (target) + && ecma_object_class_is (ecma_get_object_from_value (target), ECMA_OBJECT_CLASS_ARRAY_BUFFER)); +} /* ecma_is_arraybuffer */ + +/** + * Helper function: return the length of the buffer inside the arraybuffer object + * + * @return uint32_t, the length of the arraybuffer + */ +uint32_t JERRY_ATTR_PURE +ecma_arraybuffer_get_length (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + return ecma_arraybuffer_is_detached (object_p) ? 0 : ext_object_p->u.cls.u3.length; +} /* ecma_arraybuffer_get_length */ + +/** + * Helper function: return the pointer to the data buffer inside the arraybuffer object + * + * @return pointer to the data buffer + */ +uint8_t *JERRY_ATTR_PURE +ecma_arraybuffer_get_buffer (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p)); + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER)) + { + return (uint8_t *) object_p + sizeof (ecma_extended_object_t); + } + + ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p; + return (uint8_t *) arraybuffer_pointer_p->buffer_p; +} /* ecma_arraybuffer_get_buffer */ + +/** + * Helper function: check if the target ArrayBuffer is detached + * + * @return true - if value is an detached ArrayBuffer object + * false - otherwise + */ +bool JERRY_ATTR_PURE +ecma_arraybuffer_is_detached (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (object_p)); + + return (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED) != 0; +} /* ecma_arraybuffer_is_detached */ + +/** + * ArrayBuffer object detaching operation + * + * See also: ES2015 24.1.1.3 + * + * @return true - if detach operation is succeeded + * false - otherwise + */ +bool +ecma_arraybuffer_detach (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */ +{ + JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)); + + if (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED) + { + return false; + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_DETACHED; + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED)) + { + return true; + } + + ext_object_p->u.cls.u1.array_buffer_flags &= (uint8_t) ~ECMA_ARRAYBUFFER_ALLOCATED; + + if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER)) + { + return true; + } + + ecma_arraybuffer_release_buffer (object_p); + return true; +} /* ecma_arraybuffer_detach */ + +/** + * ArrayBuffer slice operation + * + * See also: + * ECMA-262 v11, 24.1.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_arraybuffer_slice (ecma_value_t this_arg, const ecma_value_t *argument_list_p, uint32_t arguments_number) +{ + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + /* 3-4. */ + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (object_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (object_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 5. */ + uint32_t len = ecma_arraybuffer_get_length (object_p); + + uint32_t start = 0; + uint32_t end = len; + + if (arguments_number > 0) + { + /* 6-7. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[0], len, &start))) + { + return ECMA_VALUE_ERROR; + } + + if (arguments_number > 1 && !ecma_is_value_undefined (argument_list_p[1])) + { + /* 8-9. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[1], len, &end))) + { + return ECMA_VALUE_ERROR; + } + } + } + + /* 10. */ + uint32_t new_len = (end >= start) ? (end - start) : 0; + + /* 11. */ + ecma_builtin_id_t buffer_builtin_id = ECMA_BUILTIN_ID_ARRAYBUFFER; + + if (ecma_is_shared_arraybuffer (this_arg)) + { + buffer_builtin_id = ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER; + } + + ecma_value_t ctor = ecma_op_species_constructor (object_p, buffer_builtin_id); + + if (ECMA_IS_VALUE_ERROR (ctor)) + { + return ctor; + } + + /* 12. */ + ecma_object_t *ctor_obj_p = ecma_get_object_from_value (ctor); + ecma_value_t new_len_value = ecma_make_uint32_value (new_len); + + ecma_value_t new_arraybuffer = ecma_op_function_construct (ctor_obj_p, ctor_obj_p, &new_len_value, 1); + + ecma_deref_object (ctor_obj_p); + ecma_free_value (new_len_value); + + if (ECMA_IS_VALUE_ERROR (new_arraybuffer)) + { + return new_arraybuffer; + } + + ecma_object_t *new_arraybuffer_p = ecma_get_object_from_value (new_arraybuffer); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + lit_utf8_byte_t *old_buf; + lit_utf8_byte_t *new_buf; + + /* 13. */ + if (!(ecma_object_class_is (new_arraybuffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (new_arraybuffer_p))) + { + ret_value = ecma_raise_type_error (ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT); + goto free_new_arraybuffer; + } + + /* 14-15. */ + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (new_arraybuffer_p)) + { + ret_value = ECMA_VALUE_ERROR; + goto free_new_arraybuffer; + } + + if (ecma_arraybuffer_is_detached (new_arraybuffer_p)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_new_arraybuffer; + } + + /* 16. */ + if (new_arraybuffer == this_arg) + { + ret_value = ecma_raise_type_error (ECMA_ERR_ARRAY_BUFFER_RETURNED_THIS_FROM_CONSTRUCTOR); + goto free_new_arraybuffer; + } + + /* 17. */ + if (ecma_arraybuffer_get_length (new_arraybuffer_p) < new_len) + { + ret_value = ecma_raise_type_error (ECMA_ERR_DERIVED_ARRAY_BUFFER_CTOR_BUFFER_TOO_SMALL); + goto free_new_arraybuffer; + } + + /* 19. */ + if (ecma_arraybuffer_is_detached (object_p)) + { + ret_value = ECMA_VALUE_ERROR; + goto free_new_arraybuffer; + } + + /* 20. */ + old_buf = ecma_arraybuffer_get_buffer (object_p); + + /* 21. */ + new_buf = ecma_arraybuffer_get_buffer (new_arraybuffer_p); + + /* 22. */ + memcpy (new_buf, old_buf + start, new_len); + +free_new_arraybuffer: + if (ret_value != ECMA_VALUE_EMPTY) + { + ecma_deref_object (new_arraybuffer_p); + } + else + { + /* 23. */ + ret_value = ecma_make_object_value (new_arraybuffer_p); + } + + return ret_value; +} /* ecma_builtin_arraybuffer_slice */ + +/** + * @} + * @} + */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.h new file mode 100644 index 00000000..6dc28b59 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-arraybuffer-object.h @@ -0,0 +1,68 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ARRAYBUFFER_OBJECT_H +#define ECMA_ARRAYBUFFER_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarraybufferobject ECMA ArrayBuffer object related routines + * @{ + */ + +/** + * Get array buffer flags. + */ +#define ECMA_ARRAYBUFFER_GET_FLAGS(arraybuffer_p) \ + (((ecma_extended_object_t *) (arraybuffer_p))->u.cls.u1.array_buffer_flags) + +/** + * Check whether the backing store is allocated for an array buffer. + */ +#define ECMA_ARRAYBUFFER_LAZY_ALLOC(arraybuffer_p) \ + (JERRY_UNLIKELY (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)) \ + && ecma_arraybuffer_allocate_buffer_throw (arraybuffer_p) == ECMA_VALUE_ERROR) + +ecma_value_t ecma_op_create_arraybuffer_object (const ecma_value_t *, uint32_t); + +/** + * Helper functions for arraybuffer. + */ +ecma_object_t *ecma_arraybuffer_create_object (uint8_t type, uint32_t length); +ecma_object_t *ecma_arraybuffer_create_object_with_buffer (uint8_t type, uint32_t length); +ecma_object_t *ecma_arraybuffer_new_object (uint32_t length); +ecma_value_t ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p); +ecma_value_t ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p); +void ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p); +uint8_t *JERRY_ATTR_PURE ecma_arraybuffer_get_buffer (ecma_object_t *obj_p); +uint32_t JERRY_ATTR_PURE ecma_arraybuffer_get_length (ecma_object_t *obj_p); +bool JERRY_ATTR_PURE ecma_arraybuffer_is_detached (ecma_object_t *obj_p); +bool ecma_arraybuffer_detach (ecma_object_t *obj_p); +bool ecma_is_arraybuffer (ecma_value_t val); +ecma_value_t +ecma_builtin_arraybuffer_slice (ecma_value_t this_arg, const ecma_value_t *argument_list_p, uint32_t arguments_number); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#endif /* !ECMA_ARRAYBUFFER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.cpp new file mode 100644 index 00000000..1e548bbc --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.cpp @@ -0,0 +1,523 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-async-generator-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-errors.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-stack.h" +#include "vm.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaasyncgeneratorobject ECMA AsyncGenerator object related routines + * @{ + */ + +/** + * Enqueue a task into the command queue of an async generator + * + * @return ecma Promise value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_async_generator_enqueue (vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_async_generator_operation_type_t operation, /**< operation */ + ecma_value_t value) /**< value argument of operation */ +{ + ecma_async_generator_task_t *task_p = (ecma_async_generator_task_t *) jmem_heap_alloc_block (sizeof (ecma_async_generator_task_t)); + + ECMA_SET_INTERNAL_VALUE_ANY_POINTER (task_p->next, NULL); + task_p->operation_value = ecma_copy_value_if_not_object (value); + task_p->operation_type = (uint8_t) operation; + + ecma_value_t result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + task_p->promise = result; + + ecma_value_t head = async_generator_object_p->extended_object.u.cls.u3.head; + + if (ECMA_IS_INTERNAL_VALUE_NULL (head)) + { + ECMA_SET_INTERNAL_VALUE_POINTER (async_generator_object_p->extended_object.u.cls.u3.head, task_p); + + if (async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_ASYNC_GENERATOR_CALLED) + { + ecma_value_t executable_object = ecma_make_object_value ((ecma_object_t *) async_generator_object_p); + ecma_enqueue_promise_async_generator_job (executable_object); + return result; + } + + async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_ASYNC_GENERATOR_CALLED; + ecma_async_generator_run (async_generator_object_p); + return result; + } + + /* Append the new task at the end. */ + ecma_async_generator_task_t *prev_task_p; + prev_task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, head); + + while (!ECMA_IS_INTERNAL_VALUE_NULL (prev_task_p->next)) + { + prev_task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, prev_task_p->next); + } + + ECMA_SET_INTERNAL_VALUE_POINTER (prev_task_p->next, task_p); + return result; +} /* ecma_async_generator_enqueue */ + +/** + * Call a function and await its return value + * + * @return ECMA_VALUE_UNDEFINED on success, error otherwise + */ +static ecma_value_t +ecma_async_yield_call (ecma_value_t function, /**< function (takes reference) */ + vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_value_t argument) /**< argument passed to the function */ +{ + ecma_value_t iterator = async_generator_object_p->iterator; + ecma_value_t result; + + if (argument == ECMA_VALUE_EMPTY) + { + result = ecma_op_function_validated_call (function, iterator, NULL, 0); + } + else + { + result = ecma_op_function_validated_call (function, iterator, &argument, 1); + } + + ecma_free_value (function); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + return ecma_promise_async_await ((ecma_extended_object_t *) async_generator_object_p, result); +} /* ecma_async_yield_call */ + +/** + * Perform an exception throw and call the approprite handler + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_async_yield_throw (vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_value_t value) /**< thrown value */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (async_generator_object_p->iterator); + ecma_value_t result = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_THROW); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (result == ECMA_VALUE_UNDEFINED) + { + result = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_RETURN); + + if (result == ECMA_VALUE_UNDEFINED) + { + return ecma_raise_type_error (ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE); + } + + result = ecma_async_yield_call (result, async_generator_object_p, ECMA_VALUE_EMPTY); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_CLOSE); + return ECMA_VALUE_UNDEFINED; + } + + result = ecma_async_yield_call (result, async_generator_object_p, value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_NEXT); + return ECMA_VALUE_UNDEFINED; +} /* ecma_async_yield_throw */ + +/** + * Execute the next task in the command queue of the async generator + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_async_generator_run (vm_executable_object_t *async_generator_object_p) /**< async generator */ +{ + JERRY_ASSERT (async_generator_object_p->extended_object.u.cls.type == ECMA_OBJECT_CLASS_ASYNC_GENERATOR); + JERRY_ASSERT (!ECMA_IS_INTERNAL_VALUE_NULL (async_generator_object_p->extended_object.u.cls.u3.head)); + + ecma_value_t head = async_generator_object_p->extended_object.u.cls.u3.head; + ecma_async_generator_task_t *task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, head); + ecma_value_t result; + + if (async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + switch (task_p->operation_type) + { + case ECMA_ASYNC_GENERATOR_DO_NEXT: + { + result = ecma_op_iterator_next (async_generator_object_p->iterator, + async_generator_object_p->frame_ctx.stack_top_p[-1], + task_p->operation_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + result = ecma_promise_async_await ((ecma_extended_object_t *) async_generator_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_NEXT); + break; + } + case ECMA_ASYNC_GENERATOR_DO_THROW: + { + result = ecma_async_yield_throw (async_generator_object_p, task_p->operation_value); + break; + } + default: + { + JERRY_ASSERT (task_p->operation_type == ECMA_ASYNC_GENERATOR_DO_RETURN); + + result = ecma_copy_value (task_p->operation_value); + result = ecma_promise_async_await ((ecma_extended_object_t *) async_generator_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + ECMA_AWAIT_CHANGE_STATE (async_generator_object_p, YIELD_OPERATION, YIELD_RETURN); + break; + } + } + + ecma_free_value_if_not_object (task_p->operation_value); + task_p->operation_value = ECMA_VALUE_UNDEFINED; + + if (result == ECMA_VALUE_UNDEFINED) + { + return ECMA_VALUE_UNDEFINED; + } + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + + async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags &= ECMA_AWAIT_CLEAR_MASK; + async_generator_object_p->iterator = ECMA_VALUE_UNDEFINED; + async_generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + + JERRY_ASSERT (async_generator_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (async_generator_object_p->frame_ctx.stack_top_p[-1])); + async_generator_object_p->frame_ctx.stack_top_p--; + + result = jcontext_take_exception (); + } + else + { + if (task_p->operation_type == ECMA_ASYNC_GENERATOR_DO_RETURN) + { + async_generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + } + else if (task_p->operation_type == ECMA_ASYNC_GENERATOR_DO_THROW) + { + async_generator_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + + result = task_p->operation_value; + ecma_ref_if_object (result); + task_p->operation_value = ECMA_VALUE_UNDEFINED; + } + + result = opfunc_resume_executable_object (async_generator_object_p, result); + + if (async_generator_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_COMPLETED) + { + JERRY_ASSERT (head == async_generator_object_p->extended_object.u.cls.u3.head); + ecma_async_generator_finalize (async_generator_object_p, result); + result = ECMA_VALUE_UNDEFINED; + } + + return result; +} /* ecma_async_generator_run */ + +/** + * Finalize the promises of an executable generator + */ +void +ecma_async_generator_finalize (vm_executable_object_t *async_generator_object_p, /**< async generator */ + ecma_value_t value) /**< final value (takes reference) */ +{ + ecma_value_t next = async_generator_object_p->extended_object.u.cls.u3.head; + ecma_async_generator_task_t *task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, next); + + if (ECMA_IS_VALUE_ERROR (value)) + { + value = jcontext_take_exception (); + ecma_reject_promise (task_p->promise, value); + } + else + { + ecma_value_t result = ecma_create_iter_result_object (value, ECMA_VALUE_TRUE); + ecma_fulfill_promise (task_p->promise, result); + ecma_free_value (result); + } + + ecma_free_value (value); + + next = task_p->next; + async_generator_object_p->extended_object.u.cls.u3.head = next; + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + + while (!ECMA_IS_INTERNAL_VALUE_NULL (next)) + { + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, next); + + if (task_p->operation_type != ECMA_ASYNC_GENERATOR_DO_THROW) + { + value = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + ecma_fulfill_promise (task_p->promise, value); + ecma_free_value (value); + } + else + { + ecma_reject_promise (task_p->promise, task_p->operation_value); + } + + ecma_free_value_if_not_object (task_p->operation_value); + + next = task_p->next; + async_generator_object_p->extended_object.u.cls.u3.head = next; + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + } +} /* ecma_async_generator_finalize */ + +/** + * Continue after an await operation is completed. + * + * @return an updated value for the value argument + */ +ecma_value_t +ecma_await_continue (vm_executable_object_t *executable_object_p, /**< executable object */ + ecma_value_t value) /**< job value (takes reference) */ +{ + ecma_await_states_t state = (ecma_await_states_t) ECMA_AWAIT_GET_STATE (executable_object_p); + + switch (state) + { + case ECMA_AWAIT_YIELD_NEXT: + case ECMA_AWAIT_YIELD_NEXT_RETURN: + { + if (!ecma_is_value_object (value)) + { + ecma_free_value (value); + return ecma_raise_type_error (ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT); + } + + ecma_object_t *result_obj_p = ecma_get_object_from_value (value); + ecma_value_t result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (result_obj_p); + return result; + } + + bool done = ecma_op_to_boolean (result); + ecma_free_value (result); + result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_VALUE); + ecma_deref_object (result_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!done) + { + ECMA_AWAIT_SET_STATE (executable_object_p, YIELD_NEXT_VALUE); + return ecma_promise_async_await ((ecma_extended_object_t *) executable_object_p, result); + } + + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + + if (state == ECMA_AWAIT_YIELD_NEXT_RETURN) + { + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + } + return result; + } + case ECMA_AWAIT_YIELD_RETURN: + { + ecma_object_t *obj_p = ecma_get_object_from_value (executable_object_p->iterator); + ecma_value_t result = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_RETURN); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (value); + return result; + } + + if (result == ECMA_VALUE_UNDEFINED) + { + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_return; + return value; + } + + result = ecma_async_yield_call (result, executable_object_p, value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + JERRY_ASSERT (result == ECMA_VALUE_UNDEFINED); + ECMA_AWAIT_CHANGE_STATE (executable_object_p, YIELD_RETURN, YIELD_NEXT_RETURN); + return ECMA_VALUE_UNDEFINED; + } + case ECMA_AWAIT_YIELD_NEXT_VALUE: + { + ECMA_AWAIT_CHANGE_STATE (executable_object_p, YIELD_NEXT_VALUE, YIELD_OPERATION); + opfunc_async_generator_yield ((ecma_extended_object_t *) executable_object_p, value); + return ECMA_VALUE_UNDEFINED; + } + case ECMA_AWAIT_YIELD_OPERATION: + { + /* Currently this is always a throw exception case. */ + ecma_value_t result = ecma_async_yield_throw (executable_object_p, value); + ecma_free_value (value); + return result; + } + case ECMA_AWAIT_YIELD_CLOSE: + { + ecma_error_msg_t msg = (ecma_is_value_object (value) ? ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE + : ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT); + + ecma_free_value (value); + return ecma_raise_type_error (msg); + } + case ECMA_AWAIT_FOR_CLOSE: + { + bool is_value_object = ecma_is_value_object (value); + ecma_free_value (value); + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + + if (!is_value_object + && VM_GET_CONTEXT_TYPE (executable_object_p->frame_ctx.stack_top_p[-1]) != VM_CONTEXT_FINALLY_THROW) + { + return ecma_raise_type_error (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT); + } + return ECMA_VALUE_EMPTY; + } + default: + { + JERRY_ASSERT (state == ECMA_AWAIT_FOR_NEXT); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (executable_object_p->frame_ctx.stack_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + JERRY_ASSERT (!(executable_object_p->frame_ctx.stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)); + + if (!ecma_is_value_object (value)) + { + ecma_free_value (value); + return ecma_raise_type_error (ECMA_ERR_VALUE_RECEIVED_BY_FOR_ASYNC_OF_IS_NOT_OBJECT); + } + + ecma_object_t *result_obj_p = ecma_get_object_from_value (value); + ecma_value_t result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (result_obj_p); + return result; + } + + bool done = ecma_op_to_boolean (result); + ecma_free_value (result); + + ecma_value_t *stack_top_p = executable_object_p->frame_ctx.stack_top_p; + JERRY_ASSERT (stack_top_p[-2] == ECMA_VALUE_UNDEFINED); + JERRY_ASSERT (ecma_is_value_object (stack_top_p[-3])); + JERRY_ASSERT (stack_top_p[-4] == ECMA_VALUE_UNDEFINED || ecma_is_value_object (stack_top_p[-4])); + + if (!done) + { + result = ecma_op_object_get_by_magic_id (result_obj_p, LIT_MAGIC_STRING_VALUE); + ecma_deref_object (result_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + /* It seems browsers call Await(result) here, although the standard does not + * requests to do so. The following code might follow browsers in the future. */ + ecma_deref_if_object (result); + stack_top_p[-1] |= VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = result; + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + return ECMA_VALUE_EMPTY; + } + + ecma_deref_object (result_obj_p); + + /* This code jumps to the end regardless of the byte code which triggered this await. */ + uint32_t context_end = VM_GET_CONTEXT_END (stack_top_p[-1]); + executable_object_p->frame_ctx.byte_code_p = executable_object_p->frame_ctx.byte_code_start_p + context_end; + + VM_MINUS_EQUAL_U16 (executable_object_p->frame_ctx.context_depth, PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION; + executable_object_p->frame_ctx.stack_top_p = stack_top_p; + + ECMA_EXECUTABLE_OBJECT_RESUME_EXEC (executable_object_p); + return ECMA_VALUE_EMPTY; + } + } +} /* ecma_await_continue */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.h new file mode 100644 index 00000000..bcd58e0f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-async-generator-object.h @@ -0,0 +1,88 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ASYNC_GENERATOR_OBJECT_H +#define ECMA_ASYNC_GENERATOR_OBJECT_H + +#include "ecma-globals.h" + +#include "vm-defines.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaasyncgeneratorobject ECMA AsyncGenerator object related routines + * @{ + */ + +/** + * AsyncGenerator command types. + */ +typedef enum +{ + ECMA_ASYNC_GENERATOR_DO_NEXT, /**< async generator next operation */ + ECMA_ASYNC_GENERATOR_DO_THROW, /**< async generator throw operation */ + ECMA_ASYNC_GENERATOR_DO_RETURN, /**< async generator return operation */ +} ecma_async_generator_operation_type_t; + +/** + * Get the state of an async yield iterator. + */ +#define ECMA_AWAIT_GET_STATE(async_generator_object_p) \ + ((async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags >> ECMA_AWAIT_STATE_SHIFT) + +/** + * Set the state of an async yield iterator. + */ +#define ECMA_AWAIT_SET_STATE(async_generator_object_p, to) \ + do \ + { \ + uint16_t extra_info = (async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags; \ + extra_info &= ((1 << ECMA_AWAIT_STATE_SHIFT) - 1); \ + extra_info |= (ECMA_AWAIT_##to) << ECMA_AWAIT_STATE_SHIFT; \ + (async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags = extra_info; \ + } while (false) + +/** + * Mask for clearing all ASYNC_AWAIT status bits + */ +#define ECMA_AWAIT_CLEAR_MASK (((1 << ECMA_AWAIT_STATE_SHIFT) - 1) - ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + +/** + * Helper macro for ECMA_AWAIT_CHANGE_STATE. + */ +#define ECMA_AWAIT_CS_HELPER(from, to) (((ECMA_AWAIT_##from) ^ (ECMA_AWAIT_##to)) << ECMA_AWAIT_STATE_SHIFT) + +/** + * Change the state of an async yield iterator. + */ +#define ECMA_AWAIT_CHANGE_STATE(async_generator_object_p, from, to) \ + ((async_generator_object_p)->extended_object.u.cls.u2.executable_obj_flags ^= ECMA_AWAIT_CS_HELPER (from, to)) + +ecma_value_t ecma_async_generator_enqueue (vm_executable_object_t *async_generator_object_p, + ecma_async_generator_operation_type_t operation, + ecma_value_t value); + +ecma_value_t ecma_async_generator_run (vm_executable_object_t *async_generator_object_p); +void ecma_async_generator_finalize (vm_executable_object_t *async_generator_object_p, ecma_value_t value); + +ecma_value_t ecma_await_continue (vm_executable_object_t *async_generator_object_p, ecma_value_t value); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ASYNC_GENERATOR_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.cpp new file mode 100644 index 00000000..c42ad875 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.cpp @@ -0,0 +1,263 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-atomics-object.h" + +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" +#include "jmem.h" + +#if JERRY_BUILTIN_ATOMICS + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaatomicsobject ECMA builtin Atomics helper functions + * @{ + */ + +/** + * Atomics validate Shared integer typedArray + * + * See also: ES11 24.4.1.1 + * + * @return ecma value + */ +ecma_value_t +ecma_validate_shared_integer_typedarray (ecma_value_t typedarray, /**< typedArray argument */ + bool waitable) /**< waitable argument */ +{ + /* 2. */ + if (!ecma_is_typedarray (typedarray)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY); + } + + /* 3-4. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 5-6. */ + if (waitable) + { + if (!(target_info.id == ECMA_BIGINT64_ARRAY || target_info.id == ECMA_INT32_ARRAY)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_NOT_SUPPORTED); + } + } + else + { + if (target_info.id == ECMA_UINT8_CLAMPED_ARRAY || target_info.id == ECMA_FLOAT32_ARRAY + || target_info.id == ECMA_FLOAT64_ARRAY) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_NOT_SUPPORTED); + } + } + + /* 7. */ + JERRY_ASSERT (target_info.array_buffer_p != NULL); + + /* 8-10. */ + ecma_object_t *buffer = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (!ecma_object_class_is (buffer, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER); + } + + return ecma_make_object_value (buffer); +} /* ecma_validate_shared_integer_typedarray */ + +/** + * Atomics validate Atomic Access + * + * See also: ES11 24.4.1.2 + * + * @return ecma value + */ +ecma_value_t +ecma_validate_atomic_access (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t request_index) /**< request_index argument */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (typedarray) + && ecma_typedarray_get_arraybuffer (ecma_get_object_from_value (typedarray)) != NULL); + + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + + /* 2. */ + ecma_number_t access_index; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (request_index, &access_index))) + { + return ECMA_VALUE_ERROR; + } + + /* 3. */ + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 4. */ + JERRY_ASSERT (access_index >= 0); + + /* 5-6. */ + if (JERRY_UNLIKELY (access_index >= target_info.length)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + + return ecma_make_number_value (access_index); +} /* ecma_validate_atomic_access */ + +/** + * Atomics read, modify, write + * + * See also: ES11 24.4.1.11 + * + * @return ecma value + */ +ecma_value_t +ecma_atomic_read_modify_write (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index, /**< index argument */ + ecma_value_t value, /**< value argument */ + ecma_atomics_op_t op) /**< operation argument */ +{ + /* 1. */ + ecma_value_t buffer = ecma_validate_shared_integer_typedarray (typedarray, false); + + if (ECMA_IS_VALUE_ERROR (buffer)) + { + return buffer; + } + + /* 2. */ + ecma_value_t idx = ecma_validate_atomic_access (typedarray, index); + + if (ECMA_IS_VALUE_ERROR (idx)) + { + return idx; + } + + /* 3. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 4-5. */ + ecma_value_t val = ECMA_VALUE_ERROR; + ecma_number_t tmp; + if (target_info.id == ECMA_BIGINT64_ARRAY || target_info.id == ECMA_BIGUINT64_ARRAY) + { + val = ecma_bigint_to_bigint (value, true); + } + else if (!ECMA_IS_VALUE_ERROR (ecma_op_to_integer (value, &tmp))) + { + val = ecma_make_number_value (tmp); + } + + if (ECMA_IS_VALUE_ERROR (val)) + { + return val; + } + + /* 6. */ + uint8_t element_size = target_info.element_size; + + /* 7. */ + ecma_typedarray_type_t element_type = target_info.id; + + /* 8. */ + uint32_t offset = target_info.offset; + + /* 9. */ + uint32_t indexed_position = ecma_number_to_uint32 (idx) * element_size + offset; + + ecma_free_value (idx); + + JERRY_UNUSED (indexed_position); + JERRY_UNUSED (element_type); + JERRY_UNUSED (val); + JERRY_UNUSED (buffer); + JERRY_UNUSED (op); + + ecma_free_value (val); + + /* 10. */ + return ecma_make_uint32_value (0); +} /* ecma_atomic_read_modify_write */ + +/** + * Atomics load + * + * See also: ES11 24.4.1.12 + * + * @return ecma value + */ +ecma_value_t +ecma_atomic_load (ecma_value_t typedarray, /**< typedArray argument */ + ecma_value_t index) /**< index argument */ +{ + ecma_value_t buffer = ecma_validate_shared_integer_typedarray (typedarray, false); + + if (ECMA_IS_VALUE_ERROR (buffer)) + { + return buffer; + } + + /* 2. */ + ecma_value_t idx = ecma_validate_atomic_access (typedarray, index); + + if (ECMA_IS_VALUE_ERROR (idx)) + { + return idx; + } + + /* 3. */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray); + ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p); + + /* 4. */ + uint8_t element_size = target_info.element_size; + + /* 5. */ + ecma_typedarray_type_t element_type = target_info.id; + + /* 6. */ + uint32_t offset = target_info.offset; + + /* 7. */ + uint32_t indexed_position = ecma_number_to_uint32 (idx) * element_size + offset; + + JERRY_UNUSED (indexed_position); + JERRY_UNUSED (element_type); + JERRY_UNUSED (buffer); + + /* 8. */ + return ecma_make_uint32_value (0); +} /* ecma_atomic_load */ + +/** + * @} + * @} + */ +#endif /* JERRY_BUILTIN_ATOMICS */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.h new file mode 100644 index 00000000..d73ae99b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-atomics-object.h @@ -0,0 +1,56 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ATOMICS_OBJECT_H +#define ECMA_ATOMICS_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_ATOMICS + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaatomicsobject ECMA builtin Atomics helper functions + * @{ + */ + +/** + * Atomics flags. + */ +typedef enum +{ + ECMA_ATOMICS_ADD, /**< Atomics add operation */ + ECMA_ATOMICS_SUBTRACT, /**< Atomics subtract operation */ + ECMA_ATOMICS_AND, /**< Atomics and operation */ + ECMA_ATOMICS_OR, /**< Atomics or operation */ + ECMA_ATOMICS_XOR, /**< Atomics xor operation */ + ECMA_ATOMICS_EXCHANGE, /**< Atomics exchange operation */ + ECMA_ATOMICS_COMPARE_EXCHANGE /**< Atomics compare exchange operation */ +} ecma_atomics_op_t; + +ecma_value_t ecma_validate_shared_integer_typedarray (ecma_value_t typedarray, bool waitable); +ecma_value_t ecma_validate_atomic_access (ecma_value_t typedarray, ecma_value_t request_index); +ecma_value_t +ecma_atomic_read_modify_write (ecma_value_t typedarray, ecma_value_t index, ecma_value_t value, ecma_atomics_op_t op); +ecma_value_t ecma_atomic_load (ecma_value_t typedarray, ecma_value_t index); +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_ATOMICS */ + +#endif /* ECMA_ATOMICS_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.cpp new file mode 100644 index 00000000..b98f27ee --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.cpp @@ -0,0 +1,1775 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-big-uint.h" + +#include "ecma-helpers.h" + +#include "jmem.h" +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_BIGINT + +JERRY_STATIC_ASSERT ((sizeof (ecma_bigint_two_digits_t) == 2 * sizeof (ecma_bigint_digit_t)), + ecma_big_int_two_digits_must_be_twice_as_long_as_ecma_big_int_digit); + +JERRY_STATIC_ASSERT (((1 << (int)ECMA_BIGINT_DIGIT_SHIFT) == (8 * sizeof (ecma_bigint_digit_t))), + ecma_bigint_digit_shift_is_incorrect); + +JERRY_STATIC_ASSERT ((((int)ECMA_BIG_UINT_BITWISE_DECREASE_LEFT << 1) == (int)ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT), + ecma_big_uint_bitwise_left_and_right_sub_option_bits_must_follow_each_other); + +/** + * Create a new BigInt value + * + * @return new BigInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_bigint_create (uint32_t size) /**< size of the new BigInt value */ +{ + JERRY_ASSERT (size > 0); + JERRY_ASSERT ((size % sizeof (ecma_bigint_digit_t)) == 0); + + if (JERRY_UNLIKELY (size > ECMA_BIGINT_MAX_SIZE)) + { + return NULL; + } + + ecma_extended_primitive_t *value_p; + + size_t mem_size = ECMA_BIGINT_GET_BYTE_SIZE (size) + sizeof (ecma_extended_primitive_t); + value_p = (ecma_extended_primitive_t *) jmem_heap_alloc_block_null_on_error (mem_size); + + if (JERRY_UNLIKELY (value_p == NULL)) + { + return NULL; + } + + value_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | ECMA_TYPE_BIGINT; + value_p->u.bigint_sign_and_size = size; + return value_p; +} /* ecma_bigint_create */ + +/** + * Extend a BigUInt value with a new data prefix value + * + * @return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_extend (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t digit) /**< new digit */ +{ + uint32_t old_size = ECMA_BIGINT_GET_SIZE (value_p); + + if (ECMA_BIGINT_SIZE_IS_ODD (old_size)) + { + value_p->u.bigint_sign_and_size += (uint32_t) sizeof (ecma_bigint_digit_t); + *ECMA_BIGINT_GET_DIGITS (value_p, old_size) = digit; + return value_p; + } + + ecma_extended_primitive_t *result_p = ecma_bigint_create (old_size + (uint32_t) sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + ecma_deref_bigint (value_p); + return NULL; + } + + memcpy (result_p + 1, value_p + 1, old_size); + ecma_deref_bigint (value_p); + + *ECMA_BIGINT_GET_DIGITS (result_p, old_size) = digit; + return result_p; +} /* ecma_big_uint_extend */ + +/** + * Count the number of leading zero bits of a digit + * + * return number of leading zero bits + */ +ecma_bigint_digit_t +ecma_big_uint_count_leading_zero (ecma_bigint_digit_t digit) /**< digit value */ +{ + ecma_bigint_digit_t shift = 4 * sizeof (ecma_bigint_digit_t); + ecma_bigint_digit_t result = 8 * sizeof (ecma_bigint_digit_t); + + do + { + ecma_bigint_digit_t value = digit >> shift; + if (value > 0) + { + digit = value; + result -= shift; + } + shift >>= 1; + } while (shift > 0); + + return result - digit; +} /* ecma_big_uint_count_leading_zero */ + +/** + * Helper function which discards the leading zero digits of a BigUInt value + * + * @return new BigUInt value, NULL on error + */ +static ecma_extended_primitive_t * +ecma_big_uint_normalize_result (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t *last_digit_p) /**< points to the end of BigUInt */ +{ + JERRY_ASSERT (last_digit_p[-1] == 0); + + ecma_bigint_digit_t *first_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + + /* The following code is tricky. The value stored in first_digit_p[-1] is the size + * of the BigUInt value, and it cannot be zero. Hence the loop below will terminate. */ + JERRY_ASSERT (first_digit_p[-1] != 0); + + do + { + --last_digit_p; + } while (last_digit_p[-1] == 0); + + JERRY_ASSERT (last_digit_p >= first_digit_p); + + if (first_digit_p == last_digit_p) + { + ecma_deref_bigint (value_p); + return ECMA_BIGINT_POINTER_TO_ZERO; + } + + uint32_t new_size = (uint32_t) ((uint8_t *) last_digit_p - (uint8_t *) first_digit_p); + + if (ECMA_BIGINT_SIZE_IS_ODD (new_size) + && ((new_size + sizeof (ecma_bigint_digit_t)) == ECMA_BIGINT_GET_SIZE (value_p))) + { + value_p->u.bigint_sign_and_size -= (uint32_t) sizeof (ecma_bigint_digit_t); + return value_p; + } + + ecma_extended_primitive_t *result_p = ecma_bigint_create (new_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + ecma_deref_bigint (value_p); + return NULL; + } + + memcpy (ECMA_BIGINT_GET_DIGITS (result_p, 0), ECMA_BIGINT_GET_DIGITS (value_p, 0), new_size); + ecma_deref_bigint (value_p); + + return result_p; +} /* ecma_big_uint_normalize_result */ + +/** + * Helper function which increases the result by 1 and extends or shrinks the BigUInt when necessary + * + * @return new BigUInt value, NULL on error + */ +static ecma_extended_primitive_t * +ecma_big_uint_increase_result (ecma_extended_primitive_t *value_p) /**< BigUInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0); + + ecma_bigint_digit_t *first_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *last_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + while (*first_digit_p == ~((ecma_bigint_digit_t) 0)) + { + *first_digit_p++ = 0; + + if (first_digit_p == last_digit_p) + { + return ecma_big_uint_extend (value_p, 1); + } + } + + (*first_digit_p)++; + + if (last_digit_p[-1] != 0) + { + return value_p; + } + + return ecma_big_uint_normalize_result (value_p, last_digit_p); +} /* ecma_big_uint_increase_result */ + +/** + * Compare two BigUInt numbers + * + * return -1, if left value < right value, 0 if they are equal, and 1 otherwise + */ +int +ecma_big_uint_compare (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + if (left_size > right_size) + { + return 1; + } + + if (left_size < right_size) + { + return -1; + } + + ecma_bigint_digit_t *start_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, left_size); + + do + { + ecma_bigint_digit_t left_value = *(--left_p); + ecma_bigint_digit_t right_value = *(--right_p); + + if (left_value < right_value) + { + return -1; + } + + if (left_value > right_value) + { + return 1; + } + } while (left_p > start_p); + + return 0; +} /* ecma_big_uint_compare */ + +/** + * In-place multiply and addition operation with digit + * + * return updated value on success, NULL if no memory is available + */ +ecma_extended_primitive_t * +ecma_big_uint_mul_digit (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t mul, /**< multiply value */ + ecma_bigint_digit_t add) /**< addition value */ +{ + JERRY_ASSERT (mul > 1); + JERRY_ASSERT (add < mul); + + if (JERRY_UNLIKELY (value_p == NULL)) + { + JERRY_ASSERT (add > 0); + + value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (value_p == NULL)) + { + return NULL; + } + + *ECMA_BIGINT_GET_DIGITS (value_p, 0) = add; + return value_p; + } + + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *current_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + ecma_bigint_digit_t carry = add; + + do + { + ecma_bigint_two_digits_t multiply_result = ((ecma_bigint_two_digits_t) *current_p) * mul; + ecma_bigint_digit_t multiply_result_low, new_carry; + + multiply_result_low = (ecma_bigint_digit_t) multiply_result; + new_carry = (ecma_bigint_digit_t) (multiply_result >> (8 * sizeof (ecma_bigint_digit_t))); + + multiply_result_low += carry; + if (multiply_result_low < carry) + { + new_carry++; + } + + *current_p++ = multiply_result_low; + carry = new_carry; + } while (current_p < end_p); + + if (carry == 0) + { + return value_p; + } + + return ecma_big_uint_extend (value_p, carry); +} /* ecma_big_uint_mul_digit */ + +/** + * Convert a BigUInt to a human readable number + * + * return char sequence on success, NULL otherwise + */ +lit_utf8_byte_t * +ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + uint32_t radix, /**< radix number between 2 and 36 */ + uint32_t *char_start_p, /**< [out] start offset of numbers */ + uint32_t *char_size_p) /**< [out] size of the output buffer */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (radix >= 2 && radix <= 36); + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + uint32_t max_size = size * 8; + + if (radix < 16) + { + if (radix >= 8) + { + /* Most frequent case. */ + max_size = (max_size + 2) / 3; + } + else if (radix >= 4) + { + max_size = (max_size + 1) >> 1; + } + } + else if (radix < 32) + { + max_size = (max_size + 3) >> 2; + } + else + { + max_size = (max_size + 4) / 5; + } + + /* This space can be used to store a sign. */ + max_size += (uint32_t) (2 * sizeof (ecma_bigint_digit_t) - 1); + max_size &= ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1); + *char_size_p = max_size; + + lit_utf8_byte_t *result_p = (lit_utf8_byte_t *) jmem_heap_alloc_block_null_on_error (max_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + memcpy (result_p, value_p + 1, size); + + ecma_bigint_digit_t *start_p = (ecma_bigint_digit_t *) (result_p + size); + ecma_bigint_digit_t *end_p = (ecma_bigint_digit_t *) result_p; + lit_utf8_byte_t *string_p = result_p + max_size; + + do + { + ecma_bigint_digit_t *current_p = (ecma_bigint_digit_t *) start_p; + ecma_bigint_digit_t remainder = 0; + + if (sizeof (uintptr_t) == sizeof (ecma_bigint_two_digits_t)) + { + do + { + ecma_bigint_two_digits_t result = *(--current_p) | ECMA_BIGINT_HIGH_DIGIT (remainder); + + *current_p = (ecma_bigint_digit_t) (result / radix); + remainder = (ecma_bigint_digit_t) (result % radix); + } while (current_p > end_p); + } + else + { + if (ECMA_BIGINT_SIZE_IS_ODD ((uintptr_t) current_p - (uintptr_t) end_p)) + { + ecma_bigint_digit_t result = *(--current_p); + *current_p = result / radix; + remainder = result % radix; + } + + while (current_p > end_p) + { + /* The following algorithm splits the 64 bit input into three numbers, extend + * them with remainder, divide them by radix, and updates the three bit ranges + * corresponding to the three numbers. */ + + const uint32_t extract_bits_low = 10; + const uint32_t extract_bits_low_mask = (uint32_t) ((1 << extract_bits_low) - 1); + const uint32_t extract_bits_high = (uint32_t) ((sizeof (ecma_bigint_digit_t) * 8) - extract_bits_low); + const uint32_t extract_bits_high_mask = (uint32_t) ((1 << extract_bits_high) - 1); + + ecma_bigint_digit_t result_high = current_p[-1]; + ecma_bigint_digit_t result_mid = (result_high & extract_bits_low_mask) << extract_bits_low; + + result_high = (result_high >> extract_bits_low) | (remainder << extract_bits_high); + result_mid |= (result_high % radix) << (extract_bits_low * 2); + result_high = (result_high / radix) << extract_bits_low; + + ecma_bigint_digit_t result_low = current_p[-2]; + result_mid |= result_low >> extract_bits_high; + result_low = (result_low & extract_bits_high_mask) | ((result_mid % radix) << extract_bits_high); + + result_mid = result_mid / radix; + + current_p[-1] = result_high | (result_mid >> extract_bits_low); + current_p[-2] = (result_low / radix) | (result_mid << extract_bits_high); + + remainder = result_low % radix; + current_p -= 2; + } + } + + *(--string_p) = + (lit_utf8_byte_t) ((remainder < 10) ? (remainder + LIT_CHAR_0) : (remainder + (LIT_CHAR_LOWERCASE_A - 10))); + JERRY_ASSERT (string_p >= (lit_utf8_byte_t *) start_p); + + if (start_p[-1] == 0) + { + start_p--; + } + } while (start_p > end_p); + + *char_start_p = (uint32_t) (string_p - result_p); + return result_p; +} /* ecma_big_uint_to_string */ + +/** + * Increase the value of a BigUInt value by 1 + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_increase (ecma_extended_primitive_t *value_p) /**< BigUInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + if (JERRY_UNLIKELY (digits_p[0] == ~((ecma_bigint_digit_t) 0) && digits_end_p[-1] == ~((ecma_bigint_digit_t) 0))) + { + do + { + digits_p++; + } while (digits_p < digits_end_p && digits_p[0] == ~((ecma_bigint_digit_t) 0)); + + if (digits_p == digits_end_p) + { + ecma_extended_primitive_t *result_value_p; + result_value_p = ecma_bigint_create ((uint32_t) (size + sizeof (ecma_bigint_digit_t))); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0, size); + *ECMA_BIGINT_GET_DIGITS (result_value_p, size) = 1; + return result_value_p; + } + + digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + while (digits_p[0] == ~((ecma_bigint_digit_t) 0)) + { + digits_p++; + *result_p++ = 0; + } + + *result_p++ = (*digits_p++) + 1; + + if (digits_p < digits_end_p) + { + memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p)); + } + return result_value_p; +} /* ecma_big_uint_increase */ + +/** + * Decrease the value of a BigUInt value by 1 + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_decrease (ecma_extended_primitive_t *value_p) /**< BigUInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + JERRY_ASSERT (size > sizeof (ecma_bigint_digit_t) || *digits_p > 1); + + if (JERRY_UNLIKELY (digits_p[0] == 0 && digits_end_p[-1] == 1)) + { + do + { + digits_p++; + JERRY_ASSERT (digits_p < digits_end_p); + } while (digits_p[0] == 0); + + if (digits_p + 1 == digits_end_p) + { + size -= (uint32_t) sizeof (ecma_bigint_digit_t); + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0xff, size); + return result_value_p; + } + + digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + while (digits_p[0] == 0) + { + digits_p++; + *result_p++ = ~((ecma_bigint_digit_t) 0); + } + + *result_p++ = (*digits_p++) - 1; + + if (digits_p < digits_end_p) + { + memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p)); + } + return result_value_p; +} /* ecma_big_uint_decrease */ + +/** + * Add right BigUInt value to the left BigUInt value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_add (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + if (left_size < right_size) + { + /* Swap values. */ + ecma_extended_primitive_t *tmp_value_p = left_value_p; + left_value_p = right_value_p; + right_value_p = tmp_value_p; + + uint32_t tmp_size = left_size; + left_size = right_size; + right_size = tmp_size; + } + + ecma_extended_primitive_t *result_p = ecma_bigint_create (left_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *current_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (result_p, right_size); + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t carry = 0; + + left_size -= right_size; + + do + { + ecma_bigint_digit_t left = *left_p++; + + if (carry == 0 || left != ~(ecma_bigint_digit_t) 0) + { + left += carry; + carry = 0; + } + else + { + left = 0; + carry = 1; + } + + ecma_bigint_digit_t right = *right_p++; + left += right; + + if (left < right) + { + JERRY_ASSERT (carry == 0); + carry = 1; + } + + *current_p++ = left; + } while (current_p < end_p); + + end_p = (ecma_bigint_digit_t *) (((uint8_t *) end_p) + left_size); + + if (carry != 0) + { + while (true) + { + if (JERRY_UNLIKELY (current_p == end_p)) + { + return ecma_big_uint_extend (result_p, 1); + } + + ecma_bigint_digit_t value = *left_p++; + + if (value != ~(ecma_bigint_digit_t) 0) + { + *current_p++ = value + 1; + break; + } + + *current_p++ = 0; + } + } + + if (current_p < end_p) + { + memcpy (current_p, left_p, (size_t) ((uint8_t *) end_p - (uint8_t *) current_p)); + } + + return result_p; +} /* ecma_big_uint_add */ + +/** + * Substract right BigUInt value from the left BigUInt value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + JERRY_ASSERT (left_size >= right_size); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (left_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *current_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (result_p, right_size); + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t carry = 0; + + left_size -= right_size; + + do + { + ecma_bigint_digit_t left = *left_p++; + ecma_bigint_digit_t right = *right_p++; + + if (carry == 0 || left != 0) + { + left -= carry; + carry = left < right; + } + else + { + left = ~(ecma_bigint_digit_t) 0; + carry = 1; + } + + *current_p++ = left - right; + } while (current_p < end_p); + + end_p = (ecma_bigint_digit_t *) (((uint8_t *) end_p) + left_size); + + if (carry != 0) + { + while (true) + { + JERRY_ASSERT (current_p < end_p); + + ecma_bigint_digit_t value = *left_p++; + + if (value != 0) + { + *current_p++ = value - 1; + break; + } + + *current_p++ = ~(ecma_bigint_digit_t) 0; + } + } + + if (current_p < end_p) + { + memcpy (current_p, left_p, (size_t) ((uint8_t *) end_p - (uint8_t *) current_p)); + return result_p; + } + + if (current_p[-1] != 0) + { + return result_p; + } + + return ecma_big_uint_normalize_result (result_p, current_p); +} /* ecma_big_uint_sub */ + +/** + * Multiply two BigUInt values + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_mul (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + if (left_size < right_size) + { + /* Swap values. */ + ecma_extended_primitive_t *tmp_value_p = left_value_p; + left_value_p = right_value_p; + right_value_p = tmp_value_p; + + uint32_t tmp_size = left_size; + left_size = right_size; + right_size = tmp_size; + } + + uint32_t result_size = left_size + right_size - (uint32_t) sizeof (ecma_bigint_digit_t); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (result_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + memset (ECMA_BIGINT_GET_DIGITS (result_p, 0), 0, result_size); + + /* Lower amount of space is allocated by default. This value provides extra space if needed. */ + ecma_bigint_digit_t extra_space[1] = { 0 }; + + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t *right_end_p = ECMA_BIGINT_GET_DIGITS (right_value_p, right_size); + ecma_bigint_digit_t *left_start_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + + ecma_bigint_digit_t *result_start_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + ecma_bigint_digit_t *result_end_p = ECMA_BIGINT_GET_DIGITS (result_p, result_size); + + do + { + ecma_bigint_two_digits_t right = *right_p++; + + if (right == 0) + { + result_start_p++; + continue; + } + + ecma_bigint_digit_t *left_p = left_start_p; + ecma_bigint_digit_t *destination_p = result_start_p; + ecma_bigint_digit_t carry = 0; + + do + { + JERRY_ASSERT (destination_p != (ecma_bigint_digit_t *) (extra_space + 1)); + + ecma_bigint_two_digits_t multiply_result; + ecma_bigint_digit_t multiply_result_low, new_carry; + ecma_bigint_digit_t value = *destination_p; + + multiply_result = ((ecma_bigint_two_digits_t) (*left_p++)) * ((ecma_bigint_two_digits_t) right); + multiply_result_low = (ecma_bigint_digit_t) multiply_result; + value += multiply_result_low; + new_carry = (ecma_bigint_digit_t) (multiply_result >> (8 * sizeof (ecma_bigint_digit_t))); + + /* The new_carry can never overflow because: + * a) If left or right is less than 0xff..ff, new_carry will be less than or equal to + * 0xff...fd, and increasing it by maximum of two (carries) cannot overflow. + * b) If left and right are both equal to 0xff..ff, multiply_result_low will be 1, + * and computing value + carry + 1 can only increase new_carry at most once. */ + + if (value < multiply_result_low) + { + JERRY_ASSERT (new_carry < ~(ecma_bigint_digit_t) 0); + new_carry++; + } + + value += carry; + + if (value < carry) + { + JERRY_ASSERT (new_carry < ~(ecma_bigint_digit_t) 0); + new_carry++; + } + + carry = new_carry; + *destination_p++ = value; + + if (destination_p == result_end_p) + { + destination_p = (ecma_bigint_digit_t *) extra_space; + } + } while (left_p < left_end_p); + + while (carry > 0) + { + JERRY_ASSERT (destination_p != (ecma_bigint_digit_t *) (extra_space + 1)); + + ecma_bigint_digit_t value = *destination_p; + + value += carry; + carry = (value < carry); + + *destination_p++ = value; + + if (destination_p == result_end_p) + { + destination_p = (ecma_bigint_digit_t *) extra_space; + } + } + + result_start_p++; + } while (right_p < right_end_p); + + if (extra_space[0] == 0) + { + return result_p; + } + + return ecma_big_uint_extend (result_p, extra_space[0]); +} /* ecma_big_uint_mul */ + +/** + * Divide left BigUInt value with right digit value + * + * return new BigUInt value, NULL on error + */ +static ecma_extended_primitive_t * +ecma_big_uint_div_digit (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_bigint_digit_t divisor_digit, /**< divisor value */ + bool is_mod) /**< true if return with remainder */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (divisor_digit > 0); + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size - sizeof (ecma_bigint_digit_t)); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + + ecma_bigint_digit_t last_digit = *left_p; + ecma_bigint_digit_t remainder = last_digit % divisor_digit; + + last_digit = last_digit / divisor_digit; + + ecma_extended_primitive_t *result_p = NULL; + ecma_bigint_digit_t *current_p = NULL; + + if (!is_mod) + { + ecma_bigint_digit_t result_size = left_size; + + if (last_digit == 0) + { + result_size -= (uint32_t) sizeof (ecma_bigint_digit_t); + } + + result_p = ecma_bigint_create (result_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + current_p = ECMA_BIGINT_GET_DIGITS (result_p, result_size); + + if (last_digit != 0) + { + *(--current_p) = last_digit; + } + } + + while (left_p > end_p) + { + const uint32_t shift = 1 << ECMA_BIGINT_DIGIT_SHIFT; + + ecma_bigint_two_digits_t result = *(--left_p) | (((ecma_bigint_two_digits_t) remainder) << shift); + + if (!is_mod) + { + *(--current_p) = (ecma_bigint_digit_t) (result / divisor_digit); + } + + remainder = (ecma_bigint_digit_t) (result % divisor_digit); + } + + if (!is_mod) + { + JERRY_ASSERT (current_p == ECMA_BIGINT_GET_DIGITS (result_p, 0)); + return result_p; + } + + if (remainder == 0) + { + return ECMA_BIGINT_POINTER_TO_ZERO; + } + + result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return NULL; + } + + *ECMA_BIGINT_GET_DIGITS (result_p, 0) = remainder; + return result_p; +} /* ecma_big_uint_div_digit */ + +/** + * Shift left a BigUInt value by a digit value + * + * return newly allocated buffer, NULL on error + */ +static ecma_bigint_digit_t * +ecma_big_uint_div_shift_left (ecma_extended_primitive_t *value_p, /**< BigUInt value */ + ecma_bigint_digit_t shift_left, /**< left shift */ + bool extend) /**< extend the result with an extra digit */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_bigint_digit_t *source_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + if (extend) + { + size += (uint32_t) sizeof (ecma_bigint_digit_t); + } + + ecma_bigint_digit_t *result_p = (ecma_bigint_digit_t *) jmem_heap_alloc_block_null_on_error (size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return result_p; + } + + if (shift_left == 0) + { + JERRY_ASSERT (extend); + + size -= (uint32_t) sizeof (ecma_bigint_digit_t); + *(ecma_bigint_digit_t *) (((uint8_t *) result_p) + size) = 0; + + memcpy (result_p, source_p, size); + return result_p; + } + + ecma_bigint_digit_t *destination_p = result_p; + ecma_bigint_digit_t carry = 0; + uint32_t shift_right = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_left; + + do + { + ecma_bigint_digit_t value = *source_p++; + + *destination_p++ = (value << shift_left) | carry; + carry = value >> shift_right; + } while (source_p < end_p); + + if (extend) + { + *destination_p++ = carry; + } + + return result_p; +} /* ecma_big_uint_div_shift_left */ + +/** + * Divide left BigUInt value with right BigUInt value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_div_mod (ecma_extended_primitive_t *dividend_value_p, /**< divider BigUInt value */ + ecma_extended_primitive_t *divisor_value_p, /**< divisor BigUInt value */ + bool is_mod) /**< true if return with remainder instead of quotient */ +{ + /* This algorithm is based on Donald Knuth’s "Algorithm D" */ + uint32_t divisor_size = ECMA_BIGINT_GET_SIZE (divisor_value_p); + + JERRY_ASSERT (divisor_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (divisor_value_p, divisor_size) != 0); + + /* The divisor must have at least two digits, so the single digit case is handled separately. */ + if (divisor_size == sizeof (ecma_bigint_digit_t)) + { + return ecma_big_uint_div_digit (dividend_value_p, *ECMA_BIGINT_GET_DIGITS (divisor_value_p, 0), is_mod); + } + + /* D1. [Normalize] */ + ecma_bigint_digit_t divisor_high = ECMA_BIGINT_GET_LAST_DIGIT (divisor_value_p, divisor_size); + ecma_bigint_digit_t shift_left = ecma_big_uint_count_leading_zero (divisor_high); + ecma_bigint_digit_t *buffer_p = ecma_big_uint_div_shift_left (dividend_value_p, shift_left, true); + ecma_bigint_digit_t *dividend_end_p; + ecma_bigint_digit_t *dividend_p; + ecma_bigint_digit_t *divisor_end_p; + ecma_bigint_digit_t divisor_low; + + if (JERRY_UNLIKELY (buffer_p == NULL)) + { + return NULL; + } + + uint32_t dividend_size = ECMA_BIGINT_GET_SIZE (dividend_value_p); + ecma_extended_primitive_t *result_p = NULL; + ecma_bigint_digit_t *divisor_p; + + JERRY_ASSERT (dividend_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (dividend_value_p, dividend_size) != 0); + JERRY_ASSERT (dividend_size >= divisor_size); + + if (shift_left > 0) + { + divisor_p = ecma_big_uint_div_shift_left (divisor_value_p, shift_left, false); + + if (JERRY_UNLIKELY (divisor_p == NULL)) + { + goto error; + } + } + else + { + divisor_p = ECMA_BIGINT_GET_DIGITS (divisor_value_p, 0); + } + + dividend_end_p = (ecma_bigint_digit_t *) (((uint8_t *) buffer_p) + dividend_size); + dividend_p = (ecma_bigint_digit_t *) (((uint8_t *) dividend_end_p) - divisor_size); + divisor_end_p = (ecma_bigint_digit_t *) (((uint8_t *) divisor_p) + divisor_size); + divisor_low = divisor_end_p[-2]; + + divisor_high = divisor_end_p[-1]; + JERRY_ASSERT ((divisor_high & (((ecma_bigint_digit_t) 1) << (8 * sizeof (ecma_bigint_digit_t) - 1))) != 0); + + do + { + /* D3. [Calculate Q′] */ + ecma_bigint_digit_t result_div; + + /* This do-while(false) statement allows local declarations and early exit. */ + do + { + ecma_bigint_digit_t result_mod; + + if (dividend_end_p[0] < divisor_high) + { + ecma_bigint_two_digits_t dividend = dividend_end_p[-1] | ECMA_BIGINT_HIGH_DIGIT (dividend_end_p[0]); + result_div = (ecma_bigint_digit_t) (dividend / divisor_high); + result_mod = (ecma_bigint_digit_t) (dividend % divisor_high); + } + else + { + JERRY_ASSERT (dividend_end_p[0] == divisor_high && dividend_end_p[-1] < divisor_high); + + result_div = ~((ecma_bigint_digit_t) 0); + result_mod = dividend_end_p[-1] + divisor_high; + + if (result_mod < divisor_high) + { + break; + } + } + + ecma_bigint_two_digits_t low_digits = ((ecma_bigint_two_digits_t) result_div) * divisor_low; + + while (low_digits > (ECMA_BIGINT_HIGH_DIGIT (result_mod) | divisor_low)) + { + result_div--; + result_mod += divisor_high; + + /* If result_mod becomes a two digit long number, the condition of the loop must be true, + * so the loop can be aborted. This loop stops after maximum of two iterations, since + * the highest bit of divisor_high is set. */ + if (result_mod < divisor_high) + { + break; + } + + /* Subtraction is faster than recomputing result_div * divisor_low. */ + low_digits -= divisor_low; + } + } while (false); + + /* D4. [Multiply and subtract] */ + ecma_bigint_digit_t *destination_p = dividend_p; + ecma_bigint_digit_t *source_p = divisor_p; + ecma_bigint_digit_t carry = 0; + + do + { + ecma_bigint_two_digits_t multiply_result = ((ecma_bigint_two_digits_t) (*source_p++)) * result_div; + ecma_bigint_digit_t multiply_result_low, new_carry; + ecma_bigint_digit_t value = *destination_p; + + /* The new carry never overflows. See the comment in ecma_big_uint_mul. */ + new_carry = (ecma_bigint_digit_t) (multiply_result >> (8 * sizeof (ecma_bigint_digit_t))); + multiply_result_low = (ecma_bigint_digit_t) multiply_result; + + if (value < multiply_result_low) + { + new_carry++; + } + + value -= multiply_result_low; + + if (value < carry) + { + new_carry++; + } + + *destination_p++ = value - carry; + carry = new_carry; + } while (source_p < divisor_end_p); + + bool negative_result = *destination_p < carry; + *destination_p -= carry; + + if (negative_result) + { + /* D6. [Add back] */ + result_div--; + + destination_p = dividend_p; + source_p = divisor_p; + carry = 0; + + do + { + ecma_bigint_digit_t left = *destination_p; + + if (carry == 0 || left != ~(ecma_bigint_digit_t) 0) + { + left += carry; + carry = 0; + } + else + { + left = 0; + carry = 1; + } + + ecma_bigint_digit_t right = *source_p++; + left += right; + + if (left < right) + { + JERRY_ASSERT (carry == 0); + carry = 1; + } + + *destination_p++ = left; + } while (source_p < divisor_end_p); + } + + *dividend_end_p = result_div; + + dividend_p--; + dividend_end_p--; + } while (dividend_p >= buffer_p); + + ecma_bigint_digit_t *source_p; + ecma_bigint_digit_t *source_end_p; + + if (is_mod) + { + source_p = buffer_p; + source_end_p = dividend_end_p; + + while (source_end_p > source_p && *source_end_p == 0) + { + source_end_p--; + } + + if ((*source_end_p >> shift_left) != 0) + { + source_end_p++; + /* This is required to reset carry below. */ + *source_end_p = 0; + } + } + else + { + source_p = dividend_end_p + 1; + source_end_p = (ecma_bigint_digit_t *) (((uint8_t *) buffer_p) + dividend_size); + + if (*source_end_p != 0) + { + source_end_p++; + } + } + + result_p = ECMA_BIGINT_POINTER_TO_ZERO; + + if (source_p < source_end_p) + { + result_p = ecma_bigint_create ((uint32_t) ((uint8_t *) source_end_p - (uint8_t *) source_p)); + + if (result_p != NULL) + { + ecma_bigint_digit_t *destination_p = ECMA_BIGINT_GET_DIGITS (result_p, 0); + + if (is_mod && shift_left > 0) + { + ecma_bigint_digit_t shift_right = shift_left; + + shift_left = (ecma_bigint_digit_t) (8 * (sizeof (ecma_bigint_digit_t)) - shift_left); + destination_p += source_end_p - source_p; + + ecma_bigint_digit_t carry = *source_end_p << shift_left; + + do + { + ecma_bigint_digit_t value = *(--source_end_p); + + *(--destination_p) = (value >> shift_right) | carry; + carry = value << shift_left; + } while (source_end_p > source_p); + } + else + { + memcpy (destination_p, source_p, (size_t) ((uint8_t *) source_end_p - (uint8_t *) source_p)); + } + } + } + +error: + jmem_heap_free_block (buffer_p, dividend_size + sizeof (ecma_bigint_digit_t)); + + if (shift_left > 0 && divisor_p != NULL) + { + jmem_heap_free_block (divisor_p, divisor_size); + } + + return result_p; +} /* ecma_big_uint_div_mod */ + +/** + * Shift left BigUInt values by an uint32 value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + uint32_t right_value) /**< shift value */ +{ + JERRY_ASSERT (right_value > 0); + + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + + uint32_t zero_size = (right_value >> ECMA_BIGINT_DIGIT_SHIFT) * (uint32_t) sizeof (ecma_bigint_digit_t); + uint32_t result_size = left_size + zero_size; + + uint32_t shift_left = right_value & ((1 << ECMA_BIGINT_DIGIT_SHIFT) - 1); + uint32_t shift_right = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_left; + + if (shift_left > 0 && (ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) >> shift_right) != 0) + { + result_size += (uint32_t) sizeof (ecma_bigint_digit_t); + } + + if (result_size > ECMA_BIGINT_MAX_SIZE) + { + return NULL; + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (result_size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + if (zero_size > 0) + { + memset (result_p, 0, zero_size); + result_p = (ecma_bigint_digit_t *) (((uint8_t *) result_p) + zero_size); + } + + if (shift_left == 0) + { + /* Shift by full digits. */ + memcpy (result_p, left_p, left_size); + return result_value_p; + } + + ecma_bigint_digit_t *left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + ecma_bigint_digit_t carry = 0; + + do + { + ecma_bigint_digit_t value = *left_p++; + + *result_p++ = (value << shift_left) | carry; + carry = value >> shift_right; + } while (left_p < left_end_p); + + if (carry > 0) + { + *result_p = carry; + } + + return result_value_p; +} /* ecma_big_uint_shift_left */ + +/** + * Shift right BigUInt values by an uint32 value + * + * @return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + uint32_t right_value, /**< shift value */ + bool increase_result) /**< increase result */ +{ + JERRY_ASSERT (right_value > 0); + + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + + uint32_t crop_size = (right_value >> ECMA_BIGINT_DIGIT_SHIFT) * (uint32_t) sizeof (ecma_bigint_digit_t); + + uint32_t shift_right = right_value & ((1 << ECMA_BIGINT_DIGIT_SHIFT) - 1); + uint32_t shift_left = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_right; + ecma_bigint_digit_t carry = 0; + + if (shift_right > 0 && (ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) >> shift_right) == 0) + { + carry = ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) << shift_left; + left_size -= (uint32_t) sizeof (ecma_bigint_digit_t); + } + + if (left_size <= crop_size) + { + if (JERRY_LIKELY (!increase_result)) + { + return ECMA_BIGINT_POINTER_TO_ZERO; + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + if (result_value_p != NULL) + { + *ECMA_BIGINT_GET_DIGITS (result_value_p, 0) = 1; + } + return result_value_p; + } + + if (JERRY_UNLIKELY (increase_result) + && (shift_right == 0 || (*ECMA_BIGINT_GET_DIGITS (left_value_p, crop_size) << shift_left) == 0)) + { + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, crop_size); + + while (left_p < left_end_p) + { + if (*left_p != 0) + { + break; + } + left_p++; + } + + if (left_p == left_end_p) + { + increase_result = false; + } + } + + uint32_t size = left_size - crop_size; + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + if (shift_right == 0) + { + memcpy (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), ECMA_BIGINT_GET_DIGITS (left_value_p, crop_size), size); + + if (JERRY_LIKELY (!increase_result)) + { + return result_value_p; + } + return ecma_big_uint_increase_result (result_value_p); + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, left_size); + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, size); + ecma_bigint_digit_t *end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + do + { + ecma_bigint_digit_t value = *(--left_p); + + *(--result_p) = (value >> shift_right) | carry; + carry = value << shift_left; + } while (result_p > end_p); + + if (JERRY_LIKELY (!increase_result)) + { + return result_value_p; + } + return ecma_big_uint_increase_result (result_value_p); +} /* ecma_big_uint_shift_right */ + +/** + * Compute the left value raised to the power of right value + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_pow (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + uint32_t right_value) /**< power value */ +{ + ecma_extended_primitive_t *result_p = ECMA_BIGINT_NUMBER_IS_ODD (right_value) ? left_value_p : NULL; + ecma_extended_primitive_t *square_p = left_value_p; + + JERRY_ASSERT (right_value >= 2); + + while (true) + { + ecma_extended_primitive_t *new_square_p = ecma_big_uint_mul (square_p, square_p); + + if (JERRY_UNLIKELY (new_square_p == NULL)) + { + if (result_p != NULL && result_p != left_value_p) + { + ecma_deref_bigint (result_p); + } + result_p = NULL; + break; + } + + if (square_p != left_value_p) + { + ecma_deref_bigint (square_p); + } + + square_p = new_square_p; + right_value >>= 1; + + if (ECMA_BIGINT_NUMBER_IS_ODD (right_value)) + { + if (result_p != NULL) + { + ecma_extended_primitive_t *new_result_p = ecma_big_uint_mul (square_p, result_p); + + if (result_p != left_value_p) + { + ecma_deref_bigint (result_p); + } + + result_p = new_result_p; + } + else + { + ecma_ref_extended_primitive (square_p); + result_p = square_p; + } + + if (JERRY_UNLIKELY (result_p == NULL) || right_value == 1) + { + break; + } + } + } + + if (square_p != left_value_p) + { + ecma_deref_bigint (square_p); + } + + return result_p; +} /* ecma_big_uint_pow */ + +/** + * Perform bitwise operations on two BigUInt numbers + * + * return new BigUInt value, NULL on error + */ +ecma_extended_primitive_t * +ecma_big_uint_bitwise_op (uint32_t operation_and_options, /**< bitwise operation type and options */ + ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */ +{ + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p); + + JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0); + JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0); + + uint32_t operation_type = ECMA_BIGINT_BITWISE_GET_OPERATION_TYPE (operation_and_options); + + switch (operation_type) + { + case ECMA_BIG_UINT_BITWISE_AND: + { + if (left_size > right_size) + { + left_size = right_size; + break; + } + /* FALLTHRU */ + } + case ECMA_BIG_UINT_BITWISE_AND_NOT: + { + if (right_size > left_size) + { + right_size = left_size; + } + break; + } + default: + { + JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_OR || operation_type == ECMA_BIG_UINT_BITWISE_XOR); + + if (right_size <= left_size) + { + break; + } + + /* Swap values. */ + ecma_extended_primitive_t *tmp_value_p = left_value_p; + left_value_p = right_value_p; + right_value_p = tmp_value_p; + + uint32_t tmp_size = left_size; + left_size = right_size; + right_size = tmp_size; + + uint32_t decrease_opts = (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_BOTH); + + /* When exactly one bit is set, invert both bits. */ + if (decrease_opts >= ECMA_BIG_UINT_BITWISE_DECREASE_LEFT && decrease_opts <= ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT) + { + operation_and_options ^= ECMA_BIG_UINT_BITWISE_DECREASE_BOTH; + } + break; + } + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (left_size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return NULL; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0); + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + ecma_bigint_digit_t *result_end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, right_size); + + if (!(operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_BOTH)) + { + JERRY_ASSERT (!(operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT)); + + if (operation_type == ECMA_BIG_UINT_BITWISE_AND) + { + do + { + *result_p++ = *left_p++ & *right_p++; + } while (result_p < result_end_p); + + if (result_p[-1] == 0) + { + return ecma_big_uint_normalize_result (result_value_p, result_p); + } + return result_value_p; + } + + if (operation_type == ECMA_BIG_UINT_BITWISE_OR) + { + do + { + *result_p++ = *left_p++ | *right_p++; + } while (result_p < result_end_p); + + if (left_size > right_size) + { + memcpy (result_p, left_p, left_size - right_size); + } + return result_value_p; + } + + JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_XOR); + + do + { + *result_p++ = *left_p++ ^ *right_p++; + } while (result_p < result_end_p); + + if (left_size > right_size) + { + memcpy (result_p, left_p, left_size - right_size); + return result_value_p; + } + + if (result_p[-1] == 0) + { + return ecma_big_uint_normalize_result (result_value_p, result_p); + } + return result_value_p; + } + + uint32_t left_carry = 0, right_carry = 0; + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_LEFT) + { + left_carry = 1; + } + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT) + { + right_carry = 1; + } + + do + { + ecma_bigint_digit_t left = (*left_p++) - left_carry; + + if (left != ~((ecma_bigint_digit_t) 0)) + { + left_carry = 0; + } + + ecma_bigint_digit_t right = (*right_p++) - right_carry; + + if (right != ~((ecma_bigint_digit_t) 0)) + { + right_carry = 0; + } + + switch (operation_type) + { + case ECMA_BIG_UINT_BITWISE_AND: + { + *result_p++ = left & right; + break; + } + case ECMA_BIG_UINT_BITWISE_OR: + { + *result_p++ = left | right; + break; + } + case ECMA_BIG_UINT_BITWISE_XOR: + { + *result_p++ = left ^ right; + break; + } + default: + { + JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_AND_NOT); + *result_p++ = left & ~right; + break; + } + } + } while (result_p < result_end_p); + + if (operation_type != ECMA_BIG_UINT_BITWISE_AND) + { + result_end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, left_size); + + if (left_carry > 0) + { + while (*left_p == 0) + { + *result_p++ = ~((ecma_bigint_digit_t) 0); + left_p++; + + JERRY_ASSERT (result_p < result_end_p); + } + + *result_p++ = *left_p++ - 1; + } + + if (result_p < result_end_p) + { + memcpy (result_p, left_p, (size_t) ((uint8_t *) result_end_p - (uint8_t *) result_p)); + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT) + { + return ecma_big_uint_increase_result (result_value_p); + } + return result_value_p; + } + } + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT) + { + return ecma_big_uint_increase_result (result_value_p); + } + + if (result_p[-1] == 0) + { + return ecma_big_uint_normalize_result (result_value_p, result_p); + } + return result_value_p; +} /* ecma_big_uint_bitwise_op */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.h new file mode 100644 index 00000000..727d780f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-big-uint.h @@ -0,0 +1,135 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BIG_UINT_H +#define ECMA_BIG_UINT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_BIGINT + +/** + * Limit of BigUInt memory allocation in JerryScript. + */ +#define ECMA_BIGINT_MAX_SIZE 0x10000 + +/** + * Unsigned type which can hold two digits. + */ +typedef uint64_t ecma_bigint_two_digits_t; + +/** + * Shift used by left/right shifting of a value. + */ +#define ECMA_BIGINT_DIGIT_SHIFT 5 + +/** + * Return with the digits of a BigInt value. + */ +#define ECMA_BIGINT_GET_DIGITS(value_p, offset) \ + ((ecma_bigint_digit_t *) (((uint8_t *) (value_p)) + sizeof (ecma_extended_primitive_t) + (offset))) + +/** + * Return with the digits of a BigInt value. + */ +#define ECMA_BIGINT_GET_LAST_DIGIT(value_p, size) *ECMA_BIGINT_GET_DIGITS (value_p, size - sizeof (ecma_bigint_digit_t)) + +/** + * Returns true if size is an odd number. + */ +#define ECMA_BIGINT_SIZE_IS_ODD(size) (((size) & sizeof (ecma_bigint_digit_t)) != 0) + +/** + * Returns a two digit value where the high digit is set to the passed digit. + */ +#define ECMA_BIGINT_HIGH_DIGIT(digit) (((ecma_bigint_two_digits_t) digit) << (8 * sizeof (ecma_bigint_digit_t))) + +/** + * Tells whether a number (usually a digit or uint32_t value) is an odd number. + */ +#define ECMA_BIGINT_NUMBER_IS_ODD(number) ((number & 0x1) != 0) + +/** + * Bitwise operation types. + */ +typedef enum +{ + ECMA_BIG_UINT_BITWISE_AND, /**< bitwise 'and' operation */ + ECMA_BIG_UINT_BITWISE_OR, /**< bitwise 'or' operation */ + ECMA_BIG_UINT_BITWISE_XOR, /**< bitwise 'xor' operation */ + ECMA_BIG_UINT_BITWISE_AND_NOT, /**< bitwise 'and not' operation */ +} ecma_big_uint_bitwise_operation_types_t; + +/** + * Returns with the type of the operation. + */ +#define ECMA_BIGINT_BITWISE_GET_OPERATION_TYPE(operation_and_options) ((operation_and_options) &0xf) + +/** + * Options for bitwise operations. + */ +typedef enum +{ + ECMA_BIG_UINT_BITWISE_DECREASE_LEFT = (1 << 4), /**< subtract 1 from left value */ + ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT = (1 << 5), /**< subtract 1 from right value */ + ECMA_BIG_UINT_BITWISE_INCREASE_RESULT = (1 << 6), /**< add 1 to the result */ +} ecma_big_uint_bitwise_options_t; + +/** + * Subtract 1 from both left and right values. + */ +#define ECMA_BIG_UINT_BITWISE_DECREASE_BOTH (ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT) + +ecma_extended_primitive_t *ecma_bigint_create (uint32_t size); +ecma_extended_primitive_t *ecma_big_uint_extend (ecma_extended_primitive_t *value_p, ecma_bigint_digit_t digit); + +ecma_bigint_digit_t ecma_big_uint_count_leading_zero (ecma_bigint_digit_t digit); + +int ecma_big_uint_compare (ecma_extended_primitive_t *left_value_p, ecma_extended_primitive_t *right_value_p); + +ecma_extended_primitive_t * +ecma_big_uint_mul_digit (ecma_extended_primitive_t *value_p, ecma_bigint_digit_t mul, ecma_bigint_digit_t add); + +uint8_t *ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, + uint32_t radix, + uint32_t *char_start_p, + uint32_t *char_size_p); + +ecma_extended_primitive_t *ecma_big_uint_increase (ecma_extended_primitive_t *value_p); +ecma_extended_primitive_t *ecma_big_uint_decrease (ecma_extended_primitive_t *value_p); + +ecma_extended_primitive_t *ecma_big_uint_add (ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); +ecma_extended_primitive_t *ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); +ecma_extended_primitive_t *ecma_big_uint_mul (ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); +ecma_extended_primitive_t *ecma_big_uint_div_mod (ecma_extended_primitive_t *dividend_value_p, + ecma_extended_primitive_t *divisor_value_p, + bool is_mod); + +ecma_extended_primitive_t *ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, uint32_t right_value); +ecma_extended_primitive_t * +ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, uint32_t right_value, bool increase_result); + +ecma_extended_primitive_t *ecma_big_uint_pow (ecma_extended_primitive_t *left_value_p, uint32_t right_value); + +ecma_extended_primitive_t *ecma_big_uint_bitwise_op (uint32_t operation_and_options, + ecma_extended_primitive_t *left_value_p, + ecma_extended_primitive_t *right_value_p); + +#endif /* JERRY_BUILTIN_BIGINT */ + +#endif /* ECMA_BIG_UINT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.cpp new file mode 100644 index 00000000..6d03cd51 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.cpp @@ -0,0 +1,66 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#if JERRY_BUILTIN_BIGINT + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabigintobject ECMA BigInt object related routines + * @{ + */ + +/** + * BigInt object creation operation. + * + * See also: ECMA-262 v11, 7.1.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_bigint_object (ecma_value_t arg) /**< argument passed to the toObject operation */ +{ + JERRY_ASSERT (ecma_is_value_bigint (arg)); + + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_BIGINT_PROTOTYPE); + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_BIGINT; + ext_object_p->u.cls.u3.value = ecma_copy_value (arg); + + return ecma_make_object_value (object_p); +} /* ecma_op_create_bigint_object */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.h new file mode 100644 index 00000000..72adefec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint-object.h @@ -0,0 +1,39 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BIGINT_OBJECT_H +#define ECMA_BIGINT_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_BIGINT + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabigintobject ECMA BigInt object related routines + * @{ + */ + +ecma_value_t ecma_op_create_bigint_object (ecma_value_t arg); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +#endif /* !ECMA_BIGINT_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.cpp new file mode 100644 index 00000000..7a4464e0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.cpp @@ -0,0 +1,1703 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-bigint.h" + +#include "ecma-big-uint.h" +#include "ecma-exceptions.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "lit-char-helpers.h" + +#if JERRY_BUILTIN_BIGINT + +/** + * Raise a not enough memory error + * + * @return ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_raise_memory_error (void) +{ + return ecma_raise_range_error (ECMA_ERR_ALLOCATE_BIGINT_VALUE); +} /* ecma_bigint_raise_memory_error */ + +/** + * Create a single digit long BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_create_from_digit (ecma_bigint_digit_t digit, /* single digit */ + bool sign) /* set ECMA_BIGINT_SIGN if true */ +{ + JERRY_ASSERT (digit != 0); + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (sign) + { + result_value_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + *ECMA_BIGINT_GET_DIGITS (result_value_p, 0) = digit; + return ecma_make_extended_primitive_value (result_value_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_create_from_digit */ + +/** + * Parse a string and create a BigInt value + * + * @return ecma BigInt value or a special value allowed by the option flags + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, /**< string represenation of the BigInt */ + lit_utf8_size_t size, /**< string size */ + uint32_t options) /**< ecma_bigint_parse_string_options_t option bits */ +{ + ecma_bigint_digit_t radix = 10; + uint32_t sign = (options & ECMA_BIGINT_PARSE_SET_NEGATIVE) ? ECMA_BIGINT_SIGN : 0; + bool allow_underscore = options & ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE; + + const lit_utf8_byte_t *string_end_p = string_p + size; + string_p = ecma_string_trim_front (string_p, string_p + size); + size = (lit_utf8_size_t) (string_end_p - string_p); + + if (size >= 3 && string_p[0] == LIT_CHAR_0) + { + radix = lit_char_to_radix (string_p[1]); + + if (radix != 10) + { + string_p += 2; + size -= 2; + } + } + else if (size >= 2) + { + if (string_p[0] == LIT_CHAR_PLUS) + { + size--; + string_p++; + } + else if (string_p[0] == LIT_CHAR_MINUS) + { + sign = ECMA_BIGINT_SIGN; + size--; + string_p++; + } + } + else if (size == 0) + { + return ECMA_BIGINT_ZERO; + } + + while (string_p < string_end_p && (*string_p == LIT_CHAR_0 || (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore))) + { + string_p++; + } + + ecma_extended_primitive_t *result_p = NULL; + + if (string_p == string_end_p) + { + return ECMA_BIGINT_ZERO; + } + + do + { + ecma_bigint_digit_t digit = radix; + + if (*string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9) + { + digit = (ecma_bigint_digit_t) (*string_p - LIT_CHAR_0); + } + else if (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore) + { + continue; + } + else + { + lit_utf8_byte_t character = (lit_utf8_byte_t) LEXER_TO_ASCII_LOWERCASE (*string_p); + + if (character >= LIT_CHAR_LOWERCASE_A && character <= LIT_CHAR_LOWERCASE_F) + { + digit = (ecma_bigint_digit_t) (character - (LIT_CHAR_LOWERCASE_A - 10)); + } + else if (ecma_string_trim_front (string_p, string_end_p) == string_end_p) + { + string_p = string_end_p; + break; + } + } + if (digit >= radix) + { + if (result_p != NULL) + { + ecma_deref_bigint (result_p); + } + + if (options & ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR) + { + return ECMA_VALUE_FALSE; + } + return ecma_raise_syntax_error (ECMA_ERR_STRING_CANNOT_BE_CONVERTED_TO_BIGINT_VALUE); + } + + result_p = ecma_big_uint_mul_digit (result_p, radix, digit); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + break; + } + } while (++string_p < string_end_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + if (options & ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR) + { + return ECMA_VALUE_NULL; + } + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_parse_string */ + +/** + * Parse a string value and create a BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_parse_string_value (ecma_value_t string, /**< ecma string */ + uint32_t options) /**< ecma_bigint_parse_string_options_t option bits */ +{ + JERRY_ASSERT (ecma_is_value_string (string)); + + ECMA_STRING_TO_UTF8_STRING (ecma_get_string_from_value (string), string_buffer_p, string_buffer_size); + + ecma_value_t result = ecma_bigint_parse_string (string_buffer_p, string_buffer_size, options); + ECMA_FINALIZE_UTF8_STRING (string_buffer_p, string_buffer_size); + + return result; +} /* ecma_bigint_parse_string_value */ + +/** + * Create a string representation for a BigInt value + * + * @return ecma string or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_string_t * +ecma_bigint_to_string (ecma_value_t value, /**< BigInt value */ + ecma_bigint_digit_t radix) /**< conversion radix */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return ecma_new_ecma_string_from_code_unit (LIT_CHAR_0); + } + + uint32_t char_start_p, char_size_p; + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (value); + lit_utf8_byte_t *string_buffer_p = ecma_big_uint_to_string (bigint_p, radix, &char_start_p, &char_size_p); + + if (JERRY_UNLIKELY (string_buffer_p == NULL)) + { + ecma_raise_range_error (ECMA_ERR_ALLOCATE_BIGINT_STRING); + return NULL; + } + + JERRY_ASSERT (char_start_p > 0); + + if (bigint_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + string_buffer_p[--char_start_p] = LIT_CHAR_MINUS; + } + + ecma_string_t *string_p; + string_p = ecma_new_ecma_string_from_ascii (string_buffer_p + char_start_p, char_size_p - char_start_p); + + jmem_heap_free_block (string_buffer_p, char_size_p); + return string_p; +} /* ecma_bigint_to_string */ + +/** + * Get the size of zero digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE(value) (((value) &0xffff) * (uint32_t) sizeof (ecma_bigint_digit_t)) + +/** + * Get the number of digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS(value) ((value) >> 20) + +/** + * Get the size of digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE(value) \ + (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (value) * (uint32_t) sizeof (ecma_bigint_digit_t)) + +/** + * Set number of digits in the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS(value) ((uint32_t) (value) << 20) + +/** + * This flag is set when the number passed to ecma_bigint_number_to_digits has fraction part + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION 0x10000 + +/** + * Convert a number to maximum of 3 digits and left shift + * + * @return packed value, ECMA_BIGINT_NUMBER_TO_DIGITS* macros can be used to decode it + */ +static uint32_t +ecma_bigint_number_to_digits (ecma_number_t number, /**< ecma number */ + ecma_bigint_digit_t *digits_p) /**< [out] BigInt digits */ +{ + if (ecma_number_is_zero (number)) + { + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (0); + } + + ecma_binary_num_t binary = ecma_number_to_binary (number); + uint32_t biased_exp = ecma_number_biased_exp (binary); + uint64_t fraction = ecma_number_fraction (binary); + + if (biased_exp < ((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1)) + { + /* Number is less than 1. */ + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (0) | ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION; + } + + biased_exp -= ((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1); + fraction |= ((uint64_t) 1) << ECMA_NUMBER_FRACTION_WIDTH; + + if (biased_exp <= ECMA_NUMBER_FRACTION_WIDTH) + { + uint32_t has_fraction = 0; + + if (biased_exp < ECMA_NUMBER_FRACTION_WIDTH + && (fraction << (biased_exp + ((8 * sizeof (uint64_t)) - ECMA_NUMBER_FRACTION_WIDTH))) != 0) + { + has_fraction |= ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION; + } + + fraction >>= ECMA_NUMBER_FRACTION_WIDTH - biased_exp; + digits_p[0] = (ecma_bigint_digit_t) fraction; + +#if JERRY_NUMBER_TYPE_FLOAT64 + digits_p[1] = (ecma_bigint_digit_t) (fraction >> (8 * sizeof (ecma_bigint_digit_t))); + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[1] == 0 ? 1 : 2) | has_fraction; +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (1) | has_fraction; +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + } + + digits_p[0] = (ecma_bigint_digit_t) fraction; +#if JERRY_NUMBER_TYPE_FLOAT64 + digits_p[1] = (ecma_bigint_digit_t) (fraction >> (8 * sizeof (ecma_bigint_digit_t))); +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + + biased_exp -= ECMA_NUMBER_FRACTION_WIDTH; + + uint32_t shift_left = biased_exp & ((8 * sizeof (ecma_bigint_digit_t)) - 1); + biased_exp = biased_exp >> ECMA_BIGINT_DIGIT_SHIFT; + + if (shift_left == 0) + { +#if JERRY_NUMBER_TYPE_FLOAT64 + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (2); +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (1); +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + } + + uint32_t shift_right = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_left; + +#if JERRY_NUMBER_TYPE_FLOAT64 + digits_p[2] = digits_p[1] >> shift_right; + digits_p[1] = (digits_p[1] << shift_left) | (digits_p[0] >> shift_right); + digits_p[0] <<= shift_left; + + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[2] == 0 ? 2 : 3); +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ + digits_p[1] = digits_p[0] >> shift_right; + digits_p[0] <<= shift_left; + + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[1] == 0 ? 1 : 2); +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +} /* ecma_bigint_number_to_digits */ + +/** + * Convert an ecma number to BigInt value + * + * See also: + * ECMA-262 v11, 20.2.1.1.1 + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_number_to_bigint (ecma_number_t number) /**< ecma number */ +{ + if (ecma_number_is_nan (number) || ecma_number_is_infinity (number)) + { + return ecma_raise_range_error (ECMA_ERR_INFINITY_OR_NAN_CANNOT_BE_CONVERTED_TO_BIGINT); + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (number, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + if (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) + { + return ecma_raise_range_error (ECMA_ERR_ONLY_INTEGER_NUMBERS_CAN_BE_CONVERTED_TO_BIGINT); + } + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + + if (digits_size == 0) + { + return ECMA_BIGINT_ZERO; + } + + uint32_t zero_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (digits_size + zero_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + uint8_t *data_p = (uint8_t *) ECMA_BIGINT_GET_DIGITS (result_p, 0); + memset (data_p, 0, zero_size); + memcpy (data_p + zero_size, digits, digits_size); + + if (number < 0) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_number_to_bigint */ + +/** + * Convert a value to BigInt value + * + * See also: + * ECMA-262 v11, 7.1.13 + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_to_bigint (ecma_value_t value, /**< any value */ + bool allow_numbers) /**< converting ecma numbers is allowed */ +{ + bool free_value = false; + + if (ecma_is_value_object (value)) + { + value = ecma_op_object_default_value (ecma_get_object_from_value (value), ECMA_PREFERRED_TYPE_NUMBER); + free_value = true; + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + } + + ecma_value_t result; + + if (ecma_is_value_string (value)) + { + result = ecma_bigint_parse_string_value (value, ECMA_BIGINT_PARSE_NO_OPTIONS); + } + else if (ecma_is_value_bigint (value)) + { + result = value; + + if (!free_value && value != ECMA_BIGINT_ZERO) + { + ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value)); + } + else + { + free_value = false; + } + } + else if (allow_numbers && ecma_is_value_number (value)) + { + result = ecma_bigint_number_to_bigint (ecma_get_number_from_value (value)); + } + else if (ecma_is_value_false (value)) + { + result = ECMA_BIGINT_ZERO; + } + else if (ecma_is_value_true (value)) + { + result = ecma_bigint_create_from_digit (1, false); + } + else + { + result = ecma_raise_type_error (ECMA_ERR_VALUE_CANNOT_BE_CONVERTED_TO_BIGINT); + } + + if (free_value) + { + ecma_free_value (value); + } + + return result; +} /* ecma_bigint_to_bigint */ + +/** + * Convert a BigInt value to number value + * + * @return ecma number value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_to_number (ecma_value_t value) /**< BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return ecma_make_integer_value (0); + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, size); + + if (size == sizeof (ecma_bigint_digit_t)) + { + if (!(value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (digits_p[-1] <= ECMA_INTEGER_NUMBER_MAX) + { + return ecma_make_integer_value ((ecma_integer_value_t) digits_p[-1]); + } + } + else if (digits_p[-1] <= -ECMA_INTEGER_NUMBER_MIN) + { + return ecma_make_integer_value (-(ecma_integer_value_t) digits_p[-1]); + } + } + + uint64_t fraction = 0; + ecma_bigint_digit_t shift_left; + + if (digits_p[-1] == 1) + { + JERRY_ASSERT (size > sizeof (ecma_bigint_digit_t)); + + fraction = ((uint64_t) digits_p[-2]) << (8 * sizeof (ecma_bigint_digit_t)); + shift_left = (uint32_t) (8 * sizeof (ecma_bigint_digit_t)); + + if (size >= 3 * sizeof (ecma_bigint_digit_t)) + { + fraction |= (uint64_t) digits_p[-3]; + } + } + else + { + shift_left = ecma_big_uint_count_leading_zero (digits_p[-1]) + 1; + + fraction = ((uint64_t) digits_p[-1]) << (8 * sizeof (ecma_bigint_digit_t) + shift_left); + + if (size >= 2 * sizeof (ecma_bigint_digit_t)) + { + fraction |= ((uint64_t) digits_p[-2]) << shift_left; + } + + if (size >= 3 * sizeof (ecma_bigint_digit_t)) + { + fraction |= ((uint64_t) digits_p[-3]) >> (8 * sizeof (ecma_bigint_digit_t) - shift_left); + } + } + + uint32_t biased_exp = (uint32_t) (((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1) + (size * 8 - shift_left)); + + /* Rounding result. */ + const uint64_t rounding_bit = (((uint64_t) 1) << (8 * sizeof (uint64_t) - ECMA_NUMBER_FRACTION_WIDTH - 1)); + bool round_up = false; + + if (fraction & rounding_bit) + { + round_up = true; + + /* IEEE_754 roundTiesToEven mode: when rounding_bit is set, and all the remaining bits + * are zero, the number needs to be rounded down the bit before rounding_bit is zero. */ + if ((fraction & ((rounding_bit << 2) - 1)) == rounding_bit) + { + round_up = false; + + if ((size >= (3 * sizeof (ecma_bigint_digit_t))) + && (shift_left == (8 * sizeof (ecma_bigint_digit_t)) + || (digits_p[-3] & ((((ecma_bigint_digit_t) 1) << shift_left) - 1)) == 0)) + { + ecma_bigint_digit_t *digits_start_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + + digits_p -= 3; + + while (digits_p > digits_start_p) + { + if (digits_p[-1] != 0) + { + round_up = true; + break; + } + digits_p--; + } + } + } + } + + if (round_up) + { + fraction += rounding_bit; + fraction >>= (8 * sizeof (uint64_t) - ECMA_NUMBER_FRACTION_WIDTH); + + if (fraction == 0) + { + biased_exp++; + } + } + else + { + fraction >>= (8 * sizeof (uint64_t) - ECMA_NUMBER_FRACTION_WIDTH); + } + + bool sign = (value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN); + ecma_number_t result; + + if (biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1) + { + result = ecma_number_create (sign, biased_exp, fraction); + } + else + { + result = ecma_number_make_infinity (sign); + } + + return ecma_make_number_value (result); +} /* ecma_bigint_to_number */ + +/** + * Returns with a BigInt if the value is BigInt, + * or the value is object, and its default value is BigInt + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_get_bigint (ecma_value_t value, /**< any value */ + bool *free_result_p) /**< [out] result should be freed */ +{ + *free_result_p = false; + + if (ecma_is_value_bigint (value)) + { + return value; + } + + if (ecma_is_value_object (value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (value); + ecma_value_t default_value = ecma_op_object_default_value (object_p, ECMA_PREFERRED_TYPE_NUMBER); + + if (ECMA_IS_VALUE_ERROR (default_value)) + { + return default_value; + } + + if (ecma_is_value_bigint (default_value)) + { + *free_result_p = (default_value != ECMA_BIGINT_ZERO); + return default_value; + } + + ecma_free_value (default_value); + } + + return ecma_raise_type_error (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER); +} /* ecma_bigint_get_bigint */ + +/** + * Create BigInt value from uint64 digits + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_create_from_digits (const uint64_t *digits_p, /**< BigInt digits */ + uint32_t size, /**< number of BigInt digits */ + bool sign) /**< sign bit, true if the result should be negative */ +{ + const uint64_t *digits_end_p = digits_p + size; + + while (digits_end_p > digits_p && digits_end_p[-1] == 0) + { + digits_end_p--; + } + + if (digits_p == digits_end_p) + { + return ECMA_BIGINT_ZERO; + } + + size = (uint32_t) (digits_end_p - digits_p); + + if (size < ECMA_BIGINT_MAX_SIZE) + { + size *= (uint32_t) sizeof (uint64_t); + } + + if ((digits_end_p[-1] >> (8 * sizeof (ecma_bigint_digit_t))) == 0) + { + size -= (uint32_t) sizeof (ecma_bigint_digit_t); + } + + ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_value_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (sign) + { + result_value_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0); + + while (digits_p < digits_end_p) + { + uint64_t digit = *digits_p++; + + result_p[0] = (ecma_bigint_digit_t) digit; + result_p[1] = (ecma_bigint_digit_t) (digit >> (8 * sizeof (ecma_bigint_digit_t))); + result_p += 2; + } + + return ecma_make_extended_primitive_value (result_value_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_create_from_digits */ + +/** + * Get the number of uint64 digits of a BigInt value + * + * @return number of uint64 digits + */ +uint32_t +ecma_bigint_get_size_in_digits (ecma_value_t value) /**< BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return 0; + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + return (size + (uint32_t) sizeof (ecma_bigint_digit_t)) / sizeof (uint64_t); +} /* ecma_bigint_get_size_in_digits */ + +/** + * Get the uint64 digits of a BigInt value + */ +void +ecma_bigint_get_digits_and_sign (ecma_value_t value, /**< BigInt value */ + uint64_t *digits_p, /**< [out] buffer for digits */ + uint32_t size, /**< buffer size in digits */ + bool *sign_p) /**< [out] sign of BigInt */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + if (sign_p != NULL) + { + *sign_p = false; + } + memset (digits_p, 0, size * sizeof (uint64_t)); + return; + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + + if (sign_p != NULL) + { + *sign_p = (value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) != 0; + } + + uint32_t bigint_size = ECMA_BIGINT_GET_SIZE (value_p); + uint32_t copy_size = bigint_size / sizeof (uint64_t); + + if (copy_size > size) + { + copy_size = size; + } + + const uint64_t *digits_end_p = digits_p + copy_size; + ecma_bigint_digit_t *source_p = ECMA_BIGINT_GET_DIGITS (value_p, 0); + + while (digits_p < digits_end_p) + { + *digits_p++ = source_p[0] | (((uint64_t) source_p[1]) << (8 * sizeof (ecma_bigint_digit_t))); + source_p += 2; + } + + size -= copy_size; + + if (size == 0) + { + return; + } + + if (ECMA_BIGINT_SIZE_IS_ODD (bigint_size)) + { + *digits_p++ = source_p[0]; + size--; + } + + if (size > 0) + { + memset (digits_p, 0, size * sizeof (uint64_t)); + } +} /* ecma_bigint_get_digits_and_sign */ + +/** + * Compare two BigInt values + * + * @return true if they are the same, false otherwise + */ +bool +ecma_bigint_is_equal_to_bigint (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO) + { + return right_value == ECMA_BIGINT_ZERO; + } + else if (right_value == ECMA_BIGINT_ZERO) + { + return false; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (left_p->u.bigint_sign_and_size != right_p->u.bigint_sign_and_size) + { + return false; + } + + uint32_t size = ECMA_BIGINT_GET_SIZE (left_p); + return memcmp (ECMA_BIGINT_GET_DIGITS (left_p, 0), ECMA_BIGINT_GET_DIGITS (right_p, 0), size) == 0; +} /* ecma_bigint_is_equal_to_bigint */ + +/** + * Compare a BigInt value and a number + * + * @return true if they are the same, false otherwise + */ +bool +ecma_bigint_is_equal_to_number (ecma_value_t left_value, /**< left BigInt value */ + ecma_number_t right_value) /**< right number value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value)); + + if (ecma_number_is_nan (right_value) || ecma_number_is_infinity (right_value)) + { + return false; + } + + if (left_value == ECMA_BIGINT_ZERO) + { + return right_value == 0; + } + + ecma_extended_primitive_t *left_value_p = ecma_get_extended_primitive_from_value (left_value); + + /* Sign must be the same. */ + if (left_value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + if (right_value > 0) + { + return false; + } + } + else if (right_value < 0) + { + return false; + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (right_value, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + if (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) + { + return false; + } + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + uint32_t zero_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + if (ECMA_BIGINT_GET_SIZE (left_value_p) != digits_size + zero_size) + { + return false; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_end_p = (ecma_bigint_digit_t *) (((uint8_t *) left_p) + zero_size); + + /* Check value bits first. */ + if (memcmp (left_end_p, digits, digits_size) != 0) + { + return false; + } + + while (left_p < left_end_p) + { + if (*left_p++ != 0) + { + return false; + } + } + + return true; +} /* ecma_bigint_is_equal_to_number */ + +/** + * Convert 0 to 1, and 1 to -1. Useful for getting sign. + */ +#define ECMA_BIGINT_TO_SIGN(value) (1 - (((int) (value)) << 1)) + +/** + * Convert 0 to -1, and 1 to 1. Useful for getting negated sign. + */ +#define ECMA_BIGINT_TO_NEGATED_SIGN(value) (-1 + (((int) (value)) << 1)) + +/** + * Compare two BigInt values + * + * return -1, if left value < right value, 0 if they are equal, 1 otherwise + */ +int +ecma_bigint_compare_to_bigint (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO) + { + if (right_value == ECMA_BIGINT_ZERO) + { + return 0; + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + return ECMA_BIGINT_TO_NEGATED_SIGN (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN); + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + uint32_t left_sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if (right_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_TO_SIGN (left_sign); + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + uint32_t right_sign = right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if ((left_sign ^ right_sign) != 0) + { + return ECMA_BIGINT_TO_SIGN (left_sign); + } + + if (left_sign == 0) + { + return ecma_big_uint_compare (left_p, right_p); + } + + return -ecma_big_uint_compare (left_p, right_p); +} /* ecma_bigint_compare_to_bigint */ + +/** + * Compare a BigInt value and a number + * + * return -1, if left value < right value, 0 if they are equal, 1 otherwise + */ +int +ecma_bigint_compare_to_number (ecma_value_t left_value, /**< left BigInt value */ + ecma_number_t right_value) /**< right number value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value)); + JERRY_ASSERT (!ecma_number_is_nan (right_value)); + + int right_invert_sign = ECMA_BIGINT_TO_SIGN (right_value > 0); + + if (left_value == ECMA_BIGINT_ZERO) + { + if (right_value == 0) + { + return 0; + } + + return right_invert_sign; + } + + ecma_extended_primitive_t *left_value_p = ecma_get_extended_primitive_from_value (left_value); + int left_sign = ECMA_BIGINT_TO_SIGN (left_value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN); + + if (right_value == 0 || left_sign == right_invert_sign) + { + /* Second condition: a positive BigInt is always greater than any negative number, and the opposite is true. */ + return left_sign; + } + + if (ecma_number_is_infinity (right_value)) + { + /* Infinity is always bigger than any BigInt number. */ + return right_invert_sign; + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (right_value, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + + if (digits_size == 0) + { + JERRY_ASSERT (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION); + /* The number is between [-1 .. 1] exclusive. */ + return left_sign; + } + + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + uint32_t right_size = digits_size + ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + if (left_size != right_size) + { + return left_size > right_size ? left_sign : -left_sign; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, right_size); + ecma_bigint_digit_t *left_end_p = (ecma_bigint_digit_t *) (((uint8_t *) left_p) - digits_size); + ecma_bigint_digit_t *digits_p = (ecma_bigint_digit_t *) (((uint8_t *) digits) + digits_size); + + do + { + ecma_bigint_digit_t left = *(--left_p); + ecma_bigint_digit_t right = *(--digits_p); + + if (left != right) + { + return left > right ? left_sign : -left_sign; + } + } while (left_p > left_end_p); + + left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + + while (left_p > left_end_p) + { + if (*(--left_p) != 0) + { + return left_sign; + } + } + + return (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) ? -left_sign : 0; +} /* ecma_bigint_compare_to_number */ + +#undef ECMA_BIGINT_TO_SIGN + +/** + * Negate a non-zero BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_negate (ecma_extended_primitive_t *value_p) /**< BigInt value */ +{ + uint32_t size = ECMA_BIGINT_GET_SIZE (value_p); + + JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + memcpy (result_p + 1, value_p + 1, size); + result_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | ECMA_TYPE_BIGINT; + result_p->u.bigint_sign_and_size = value_p->u.bigint_sign_and_size ^ ECMA_BIGINT_SIGN; + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_negate */ + +/** + * Invert all bits of a BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_unary (ecma_value_t value, /**< BigInt value */ + ecma_bigint_unary_operation_type type) /**< type of unary operation */ +{ + JERRY_ASSERT (ecma_is_value_bigint (value)); + + if (value == ECMA_BIGINT_ZERO) + { + return ecma_bigint_create_from_digit (1, type != ECMA_BIGINT_UNARY_INCREASE); + } + + ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value); + + uint32_t sign = (type != ECMA_BIGINT_UNARY_DECREASE) ? ECMA_BIGINT_SIGN : 0; + + if ((value_p->u.bigint_sign_and_size == (uint32_t) (sizeof (ecma_bigint_digit_t) | sign)) + && *ECMA_BIGINT_GET_DIGITS (value_p, 0) == 1) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *result_p; + + if ((value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) == (sign ^ ECMA_BIGINT_SIGN)) + { + result_p = ecma_big_uint_increase (value_p); + + if (type != ECMA_BIGINT_UNARY_INCREASE && result_p != NULL) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + } + else + { + result_p = ecma_big_uint_decrease (value_p); + + if (type == ECMA_BIGINT_UNARY_INCREASE && result_p != NULL) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_unary */ + +/** + * Add/subtract right BigInt value to/from left BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_add_sub (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value, /**< right BigInt value */ + bool is_add) /**< true if add operation should be performed */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (left_value); + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (left_value == ECMA_BIGINT_ZERO) + { + if (!is_add) + { + return ecma_bigint_negate (right_p); + } + + ecma_ref_extended_primitive (right_p); + return right_value; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + uint32_t sign = is_add ? 0 : ECMA_BIGINT_SIGN; + + if (((left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN) == sign) + { + ecma_extended_primitive_t *result_p = ecma_big_uint_add (left_p, right_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); + } + + int compare_result = ecma_big_uint_compare (left_p, right_p); + ecma_extended_primitive_t *result_p; + + if (compare_result == 0) + { + return ECMA_BIGINT_ZERO; + } + + if (compare_result > 0) + { + sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + result_p = ecma_big_uint_sub (left_p, right_p); + } + else + { + sign = right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if (!is_add) + { + sign ^= ECMA_BIGINT_SIGN; + } + + result_p = ecma_big_uint_sub (right_p, left_p); + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_add_sub */ + +/** + * Multiply two BigInt values + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_mul (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO || right_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_p); + uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p); + + if (left_size == sizeof (ecma_bigint_digit_t) + && ECMA_BIGINT_GET_LAST_DIGIT (left_p, sizeof (ecma_bigint_digit_t)) == 1) + { + if (left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + return ecma_bigint_negate (right_p); + } + + ecma_ref_extended_primitive (right_p); + return right_value; + } + + if (right_size == sizeof (ecma_bigint_digit_t) + && ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t)) == 1) + { + if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + return ecma_bigint_negate (left_p); + } + + ecma_ref_extended_primitive (left_p); + return left_value; + } + + ecma_extended_primitive_t *result_p = ecma_big_uint_mul (left_p, right_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + uint32_t sign = (left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN; + result_p->u.bigint_sign_and_size |= sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_mul */ + +/** + * Divide two BigInt values + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_div_mod (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value, /**< right BigInt value */ + bool is_mod) /**< true if return with remainder */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_raise_range_error (ECMA_ERR_BIGINT_ZERO_DIVISION); + } + + if (left_value == ECMA_BIGINT_ZERO) + { + return left_value; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + int compare_result = ecma_big_uint_compare (left_p, right_p); + ecma_extended_primitive_t *result_p; + + if (compare_result < 0) + { + if (!is_mod) + { + return ECMA_BIGINT_ZERO; + } + + ecma_ref_extended_primitive (left_p); + return left_value; + } + else if (compare_result == 0) + { + if (is_mod) + { + return ECMA_BIGINT_ZERO; + } + + result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t)); + + if (result_p != NULL) + { + *ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1; + } + } + else + { + result_p = ecma_big_uint_div_mod (left_p, right_p, is_mod); + + if (result_p == ECMA_BIGINT_POINTER_TO_ZERO) + { + return ECMA_BIGINT_ZERO; + } + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (is_mod) + { + result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + } + else + { + uint32_t sign = (left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN; + result_p->u.bigint_sign_and_size |= sign; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_div_mod */ + +/** + * Shift left BigInt value to left or right + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_shift (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value, /**< right BigInt value */ + bool is_left) /**< true if left shift operation should be performed */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (left_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + + if (right_value == ECMA_BIGINT_ZERO) + { + ecma_ref_extended_primitive (left_p); + return left_value; + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + is_left = !is_left; + } + + if (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t)) + { + if (is_left) + { + return ecma_bigint_raise_memory_error (); + } + else if (left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + /* Shifting a negative value with a very big number to the right should be -1. */ + return ecma_bigint_create_from_digit (1, true); + } + + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *result_p; + ecma_bigint_digit_t shift = ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t)); + uint32_t left_sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if (is_left) + { + result_p = ecma_big_uint_shift_left (left_p, shift); + } + else + { + /* -x >> y == ~(x - 1) >> y == ~((x - 1) >> y) == -(((x - 1) >> y) + 1) + * When a non-zero bit is shifted out: (x - 1) >> y == x >> y, so the formula is -((x >> y) + 1) + * When only zero bits are shifted out: (((x - 1) >> y) + 1) == x >> y so the formula is: -(x >> y) */ + result_p = ecma_big_uint_shift_right (left_p, shift, left_sign != 0); + + if (result_p == ECMA_BIGINT_POINTER_TO_ZERO) + { + return ECMA_BIGINT_ZERO; + } + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + result_p->u.bigint_sign_and_size |= left_sign; + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_shift */ + +/** + * Compute the left value raised to the power of right value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_pow (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_bigint_create_from_digit (1, false); + } + + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + return ecma_raise_range_error (ECMA_ERR_NEGATIVE_EXPONENT_IS_NOT_ALLOWED_FOR_BIGINTS); + } + + if (left_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_bigint_digit_t base = 0; + + if (ECMA_BIGINT_GET_SIZE (left_p) == sizeof (ecma_bigint_digit_t)) + { + base = *ECMA_BIGINT_GET_DIGITS (left_p, 0); + + JERRY_ASSERT (base != 0); + + if (base == 1) + { + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + || ECMA_BIGINT_NUMBER_IS_ODD (*ECMA_BIGINT_GET_DIGITS (right_p, 0))) + { + ecma_ref_extended_primitive (left_p); + return left_value; + } + + return ecma_bigint_create_from_digit (1, false); + } + } + + if (JERRY_UNLIKELY (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t))) + { + return ecma_bigint_raise_memory_error (); + } + + ecma_bigint_digit_t power = *ECMA_BIGINT_GET_DIGITS (right_p, 0); + + if (power == 1) + { + ecma_ref_extended_primitive (left_p); + return left_value; + } + + ecma_extended_primitive_t *result_p; + + if (base == 2) + { + result_p = ecma_big_uint_shift_left (left_p, power - 1); + } + else + { + result_p = ecma_big_uint_pow (left_p, power); + } + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if ((left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) && ECMA_BIGINT_NUMBER_IS_ODD (power)) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_pow */ + +/** + * Convert the result to an ecma value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_bigint_bitwise_op (uint32_t operation_and_options, /**< bitwise operation type and options */ + ecma_extended_primitive_t *left_value_p, /**< left BigInt value */ + ecma_extended_primitive_t *right_value_p) /**< right BigInt value */ +{ + ecma_extended_primitive_t *result_p; + result_p = ecma_big_uint_bitwise_op (operation_and_options, left_value_p, right_value_p); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (result_p == ECMA_BIGINT_POINTER_TO_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_bitwise_op */ + +/** + * Perform bitwise 'and' operations on two BigUInt numbers + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_and (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + if (left_value == ECMA_BIGINT_ZERO || right_value == ECMA_BIGINT_ZERO) + { + return ECMA_BIGINT_ZERO; + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_AND, left_p, right_p); + } + + /* x & (-y) == x & ~(y-1) == x &~ (y-1) */ + uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT; + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + /* (-x) & y == ~(x-1) & y == y &~ (x-1) */ + uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT; + return ecma_bigint_bitwise_op (operation_and_options, right_p, left_p); + } + + /* (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_OR | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); +} /* ecma_bigint_and */ + +/** + * Perform bitwise 'or' operations on two BigUInt numbers + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_or (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + if (left_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (right_value); + } + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (left_value); + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_OR, left_p, right_p); + } + + /* x | (-y) == x | ~(y-1) == ~((y-1) &~ x) == -(((y-1) &~ x) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, right_p, left_p); + } + + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + /* (-x) | y == ~(x-1) | y == ~((x-1) &~ y) == -(((x-1) &~ y) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + /* (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1)) = -(((x-1) & (y-1)) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_AND | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); +} /* ecma_bigint_or */ + +/** + * Perform bitwise 'xor' operations on two BigUInt numbers + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_xor (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + if (left_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (right_value); + } + + if (right_value == ECMA_BIGINT_ZERO) + { + return ecma_copy_value (left_value); + } + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_XOR, left_p, right_p); + } + + /* x ^ (-y) == x ^ ~(y-1) == ~(x ^ (y-1)) == -((x ^ (y-1)) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_XOR | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)) + { + /* (-x) | y == ~(x-1) ^ y == ~((x-1) ^ y) == -(((x-1) ^ y) + 1) */ + uint32_t operation_and_options = + (ECMA_BIG_UINT_BITWISE_XOR | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT); + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); + } + + /* (-x) ^ (-y) == ~(x-1) ^ ~(y-1) == (x-1) ^ (y-1) */ + uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_XOR | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH; + return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p); +} /* ecma_bigint_xor */ + +#endif /* JERRY_BUILTIN_BIGINT */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.h new file mode 100644 index 00000000..460ed769 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-bigint.h @@ -0,0 +1,81 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BIG_INT_H +#define ECMA_BIG_INT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_BIGINT + +/** + * Sign bit of a BigInt value. The number is negative, if this bit is set. + */ +#define ECMA_BIGINT_SIGN 0x1 + +/** + * Flags for ecma_bigint_parse_string. + */ +typedef enum +{ + ECMA_BIGINT_PARSE_NO_OPTIONS = 0, /**< no options */ + ECMA_BIGINT_PARSE_SET_NEGATIVE = (1 << 0), /**< return with a negative BigInt value */ + ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR = (1 << 1), /**< don't throw SyntaxError, + * return with ECMA_VALUE_FALSE */ + ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR = (1 << 2), /**< don't throw out-of-memory error, + * return with ECMA_VALUE_NULL instead */ + ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE = (1 << 3), /** allow parse underscore characters */ +} ecma_bigint_parse_string_options_t; + +/** + * Types for unary operations + */ +typedef enum +{ + ECMA_BIGINT_UNARY_BITWISE_NOT, /**< bitwise not operation */ + ECMA_BIGINT_UNARY_INCREASE, /**< increase operation */ + ECMA_BIGINT_UNARY_DECREASE, /**< decrease operation */ +} ecma_bigint_unary_operation_type; + +ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8_size_t size, uint32_t options); +ecma_value_t ecma_bigint_parse_string_value (ecma_value_t string, uint32_t options); +ecma_string_t *ecma_bigint_to_string (ecma_value_t value, ecma_bigint_digit_t radix); +ecma_value_t ecma_bigint_to_bigint (ecma_value_t value, bool allow_numbers); +ecma_value_t ecma_bigint_to_number (ecma_value_t value); +ecma_value_t ecma_bigint_get_bigint (ecma_value_t value, bool *free_result_p); +ecma_value_t ecma_bigint_create_from_digits (const uint64_t *digits_p, uint32_t size, bool sign); +uint32_t ecma_bigint_get_size_in_digits (ecma_value_t value); +void ecma_bigint_get_digits_and_sign (ecma_value_t value, uint64_t *digits_p, uint32_t size, bool *sign_p); + +bool ecma_bigint_is_equal_to_bigint (ecma_value_t left_value, ecma_value_t right_value); +bool ecma_bigint_is_equal_to_number (ecma_value_t left_value, ecma_number_t right_value); +int ecma_bigint_compare_to_bigint (ecma_value_t left_value, ecma_value_t right_value); +int ecma_bigint_compare_to_number (ecma_value_t left_value, ecma_number_t right_value); + +ecma_value_t ecma_bigint_negate (ecma_extended_primitive_t *value_p); +ecma_value_t ecma_bigint_unary (ecma_value_t value, ecma_bigint_unary_operation_type type); +ecma_value_t ecma_bigint_add_sub (ecma_value_t left_value, ecma_value_t right_value, bool is_add); +ecma_value_t ecma_bigint_mul (ecma_value_t left_value, ecma_value_t right_value); +ecma_value_t ecma_bigint_div_mod (ecma_value_t left_value, ecma_value_t right_value, bool is_mod); +ecma_value_t ecma_bigint_shift (ecma_value_t left_value, ecma_value_t right_value, bool is_left); +ecma_value_t ecma_bigint_pow (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t ecma_bigint_and (ecma_value_t left_value, ecma_value_t right_value); +ecma_value_t ecma_bigint_or (ecma_value_t left_value, ecma_value_t right_value); +ecma_value_t ecma_bigint_xor (ecma_value_t left_value, ecma_value_t right_value); + +#endif /* JERRY_BUILTIN_BIGINT */ + +#endif /* ECMA_BIG_INT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.cpp new file mode 100644 index 00000000..956aa4a7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.cpp @@ -0,0 +1,88 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-boolean-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabooleanobject ECMA Boolean object related routines + * @{ + */ + +/** + * Boolean object creation operation. + * + * See also: ECMA-262 v5, 15.6.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_boolean_object (ecma_value_t arg) /**< argument passed to the Boolean constructor */ +{ + bool boolean_value = ecma_op_to_boolean (arg); + ecma_builtin_id_t proto_id; + +#if JERRY_BUILTIN_BOOLEAN + proto_id = ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE; +#else /* JERRY_BUILTIN_BOOLEAN */ + proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; +#endif /* !(JERRY_BUILTIN_BOOLEAN */ + + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + ecma_object_t *new_target = JERRY_CONTEXT (current_new_target_p); + if (new_target) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (new_target, proto_id); + + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_BOOLEAN; + ext_object_p->u.cls.u3.value = ecma_make_boolean_value (boolean_value); + + if (new_target) + { + ecma_deref_object (prototype_obj_p); + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_boolean_object */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.h new file mode 100644 index 00000000..adf0353d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_BOOLEAN_OBJECT_H +#define ECMA_BOOLEAN_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabooleanobject ECMA Boolean object related routines + * @{ + */ + +ecma_value_t ecma_op_create_boolean_object (ecma_value_t arg); + +/** + * @} + * @} + */ + +#endif /* !ECMA_BOOLEAN_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.cpp new file mode 100644 index 00000000..5a32a2c6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.cpp @@ -0,0 +1,536 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-comparison.h" + +#include "ecma-bigint.h" +#include "ecma-conversion.h" +#include "ecma-globals.h" +#include "ecma-objects.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmacomparison ECMA comparison + * @{ + */ + +/** + * ECMA abstract equality comparison routine. + * + * See also: ECMA-262 v5, 11.9.3 + * + * Note: + * This function might raise an exception, so the + * returned value must be freed with ecma_free_value. + * + * @return true - if values are equal, + * false - otherwise + * error - in case of any problems + */ +ecma_value_t +ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ + ecma_value_t y) /**< second operand */ +{ + if (x == y) + { + return ECMA_VALUE_TRUE; + } + + if (ecma_are_values_integer_numbers (x, y)) + { + /* Note: the (x == y) comparison captures the true case. */ + return ECMA_VALUE_FALSE; + } + + if (ecma_is_value_number (x)) + { + if (ecma_is_value_number (y)) + { + /* 1.c */ + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_equal_to_y = (x_num == y_num); + +#ifndef JERRY_NDEBUG + bool is_x_equal_to_y_check; + + if (ecma_number_is_nan (x_num) || ecma_number_is_nan (y_num)) + { + is_x_equal_to_y_check = false; + } + else if (x_num == y_num || (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num))) + { + is_x_equal_to_y_check = true; + } + else + { + is_x_equal_to_y_check = false; + } + + JERRY_ASSERT (is_x_equal_to_y == is_x_equal_to_y_check); +#endif /* !JERRY_NDEBUG */ + + return ecma_make_boolean_value (is_x_equal_to_y); + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } + + if (ecma_is_value_string (x)) + { + if (ecma_is_value_string (y)) + { + /* 1., d. */ + ecma_string_t *x_str_p = ecma_get_string_from_value (x); + ecma_string_t *y_str_p = ecma_get_string_from_value (y); + + bool is_equal = ecma_compare_ecma_strings (x_str_p, y_str_p); + + return ecma_make_boolean_value (is_equal); + } + + if (ecma_is_value_number (y)) + { + /* 4. */ + ecma_number_t num; + ecma_value_t x_num_value = ecma_op_to_number (x, &num); + + if (ECMA_IS_VALUE_ERROR (x_num_value)) + { + return x_num_value; + } + ecma_value_t num_value = ecma_make_number_value (num); + ecma_value_t compare_result = ecma_op_abstract_equality_compare (num_value, y); + + ecma_free_value (num_value); + return compare_result; + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } + + if (ecma_is_value_boolean (y)) + { + if (ecma_is_value_boolean (x)) + { + /* 1., e. */ + /* Note: the (x == y) comparison captures the true case. */ + return ECMA_VALUE_FALSE; + } + + /* 7. */ + return ecma_op_abstract_equality_compare (x, ecma_make_integer_value (ecma_is_value_true (y) ? 1 : 0)); + } + + if (ecma_is_value_boolean (x)) + { + /* 6. */ + return ecma_op_abstract_equality_compare (ecma_make_integer_value (ecma_is_value_true (x) ? 1 : 0), y); + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_UNLIKELY (ecma_is_value_bigint (x))) + { + if (ecma_is_value_bigint (y)) + { + return ecma_make_boolean_value (ecma_bigint_is_equal_to_bigint (x, y)); + } + + if (ecma_is_value_string (y)) + { + ecma_value_t bigint = ecma_bigint_parse_string_value (y, ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR); + + if (ECMA_IS_VALUE_ERROR (bigint) || bigint == ECMA_VALUE_FALSE) + { + return bigint; + } + + JERRY_ASSERT (ecma_is_value_bigint (bigint)); + + ecma_value_t result = ecma_make_boolean_value (ecma_bigint_is_equal_to_bigint (x, bigint)); + + ecma_free_value (bigint); + return result; + } + + if (ecma_is_value_number (y)) + { + return ecma_make_boolean_value (ecma_bigint_is_equal_to_number (x, ecma_get_number_from_value (y))); + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + if (ecma_is_value_undefined (x) || ecma_is_value_null (x)) + { + /* 1. a., b. */ + /* 2., 3. */ + bool is_equal = ecma_is_value_undefined (y) || ecma_is_value_null (y); + + return ecma_make_boolean_value (is_equal); + } + + if (JERRY_UNLIKELY (ecma_is_value_symbol (x))) + { + if (!ecma_is_value_object (y)) + { + return ECMA_VALUE_FALSE; + } + + /* Swap values. */ + x ^= y; + y ^= x; + x ^= y; + } + + JERRY_ASSERT (ecma_is_value_object (x)); + + if (ecma_is_value_string (y) || ecma_is_value_symbol (y) +#if JERRY_BUILTIN_BIGINT + || ecma_is_value_bigint (y) +#endif /* JERRY_BUILTIN_BIGINT */ + || ecma_is_value_number (y)) + { + /* 9. */ + ecma_object_t *obj_p = ecma_get_object_from_value (x); + + ecma_value_t def_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); + + if (ECMA_IS_VALUE_ERROR (def_value)) + { + return def_value; + } + + ecma_value_t compare_result = ecma_op_abstract_equality_compare (def_value, y); + + ecma_free_value (def_value); + + return compare_result; + } + + return ECMA_VALUE_FALSE; +} /* ecma_op_abstract_equality_compare */ + +/** + * ECMA strict equality comparison routine. + * + * See also: ECMA-262 v5, 11.9.6 + * + * @return true - if values are strict equal, + * false - otherwise + */ +bool +ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */ + ecma_value_t y) /**< second operand */ +{ + if (ecma_is_value_direct (x) || ecma_is_value_direct (y) || ecma_is_value_symbol (x) || ecma_is_value_symbol (y) + || ecma_is_value_object (x) || ecma_is_value_object (y)) + { + JERRY_ASSERT (!ecma_is_value_direct (x) || ecma_is_value_undefined (x) || ecma_is_value_null (x) + || ecma_is_value_boolean (x) || ecma_is_value_integer_number (x)); + + JERRY_ASSERT (!ecma_is_value_direct (y) || ecma_is_value_undefined (y) || ecma_is_value_null (y) + || ecma_is_value_boolean (y) || ecma_is_value_integer_number (y)); + + if ((x != ecma_make_integer_value (0) || !ecma_is_value_float_number (y)) + && (y != ecma_make_integer_value (0) || !ecma_is_value_float_number (x))) + { + return (x == y); + } + + /* The +0 === -0 case handled below. */ + } + + JERRY_ASSERT (ecma_is_value_number (x) || ecma_is_value_string (x) || ecma_is_value_bigint (x)); + JERRY_ASSERT (ecma_is_value_number (y) || ecma_is_value_string (y) || ecma_is_value_bigint (y)); + + if (ecma_is_value_string (x)) + { + if (!ecma_is_value_string (y)) + { + return false; + } + + ecma_string_t *x_str_p = ecma_get_string_from_value (x); + ecma_string_t *y_str_p = ecma_get_string_from_value (y); + + return ecma_compare_ecma_strings (x_str_p, y_str_p); + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_UNLIKELY (ecma_is_value_bigint (x))) + { + if (!ecma_is_value_bigint (y)) + { + return false; + } + + return ecma_bigint_is_equal_to_bigint (x, y); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + if (!ecma_is_value_number (y)) + { + return false; + } + + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_equal_to_y = (x_num == y_num); + +#ifndef JERRY_NDEBUG + bool is_x_equal_to_y_check; + + if (ecma_number_is_nan (x_num) || ecma_number_is_nan (y_num)) + { + is_x_equal_to_y_check = false; + } + else if (x_num == y_num || (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num))) + { + is_x_equal_to_y_check = true; + } + else + { + is_x_equal_to_y_check = false; + } + + JERRY_ASSERT (is_x_equal_to_y == is_x_equal_to_y_check); +#endif /* !JERRY_NDEBUG */ + + return is_x_equal_to_y; +} /* ecma_op_strict_equality_compare */ + +/** + * ECMA abstract relational comparison routine. + * + * See also: ECMA-262 v5, 11.8.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_abstract_relational_compare (ecma_value_t x, /**< first operand */ + ecma_value_t y, /**< second operand */ + bool left_first) /**< 'LeftFirst' flag */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 1., 2. */ + ecma_value_t prim_first_converted_value = ecma_op_to_primitive (x, ECMA_PREFERRED_TYPE_NUMBER); + if (ECMA_IS_VALUE_ERROR (prim_first_converted_value)) + { + return prim_first_converted_value; + } + + ecma_value_t prim_second_converted_value = ecma_op_to_primitive (y, ECMA_PREFERRED_TYPE_NUMBER); + if (ECMA_IS_VALUE_ERROR (prim_second_converted_value)) + { + ecma_free_value (prim_first_converted_value); + return prim_second_converted_value; + } + + ecma_value_t px = left_first ? prim_first_converted_value : prim_second_converted_value; + ecma_value_t py = left_first ? prim_second_converted_value : prim_first_converted_value; + + const bool is_px_string = ecma_is_value_string (px); + const bool is_py_string = ecma_is_value_string (py); + + if (!(is_px_string && is_py_string)) + { +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (px)) && JERRY_LIKELY (!ecma_is_value_bigint (py))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + /* 3. */ + + /* a. */ + + ecma_number_t nx; + ecma_number_t ny; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (px, &nx)) || ECMA_IS_VALUE_ERROR (ecma_op_to_number (py, &ny))) + { + ret_value = ECMA_VALUE_ERROR; + goto end; + } + + /* b. */ + if (ecma_number_is_nan (nx) || ecma_number_is_nan (ny)) + { + /* c., d. */ + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + bool is_x_less_than_y = (nx < ny); + +#ifndef JERRY_NDEBUG + bool is_x_less_than_y_check; + + if (nx == ny || (ecma_number_is_zero (nx) && ecma_number_is_zero (ny))) + { + /* e., f., g. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (nx) && !ecma_number_is_negative (nx)) + { + /* h. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (ny) && !ecma_number_is_negative (ny)) + { + /* i. */ + is_x_less_than_y_check = true; + } + else if (ecma_number_is_infinity (ny) && ecma_number_is_negative (ny)) + { + /* j. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (nx) && ecma_number_is_negative (nx)) + { + /* k. */ + is_x_less_than_y_check = true; + } + else + { + /* l. */ + JERRY_ASSERT (!ecma_number_is_nan (nx) && !ecma_number_is_infinity (nx)); + JERRY_ASSERT (!ecma_number_is_nan (ny) && !ecma_number_is_infinity (ny)); + JERRY_ASSERT (!(ecma_number_is_zero (nx) && ecma_number_is_zero (ny))); + + if (nx < ny) + { + is_x_less_than_y_check = true; + } + else + { + is_x_less_than_y_check = false; + } + } + + JERRY_ASSERT (is_x_less_than_y_check == is_x_less_than_y); +#endif /* !JERRY_NDEBUG */ + + ret_value = ecma_make_boolean_value (is_x_less_than_y); + } +#if JERRY_BUILTIN_BIGINT + } + else + { + bool invert_result = false; + int compare_result = 0; + + if (!ecma_is_value_bigint (px)) + { + ecma_value_t tmp = px; + px = py; + py = tmp; + invert_result = true; + } + + JERRY_ASSERT (ecma_is_value_bigint (px)); + + if (ecma_is_value_bigint (py)) + { + compare_result = ecma_bigint_compare_to_bigint (px, py); + } + else if (ecma_is_value_string (py)) + { + ret_value = ecma_bigint_parse_string_value (py, ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + if (ret_value == ECMA_VALUE_FALSE) + { + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + compare_result = ecma_bigint_compare_to_bigint (px, ret_value); + ecma_free_value (ret_value); + ret_value = ECMA_VALUE_EMPTY; + } + } + } + else + { + ecma_number_t ny; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (py, &ny))) + { + ret_value = ECMA_VALUE_ERROR; + goto end; + } + + if (ecma_number_is_nan (ny)) + { + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + compare_result = ecma_bigint_compare_to_number (px, ny); + } + } + + if (ret_value == ECMA_VALUE_EMPTY) + { + if (invert_result) + { + compare_result = -compare_result; + } + + ret_value = ecma_make_boolean_value (compare_result < 0); + } + } +#endif /* JERRY_BUILTIN_BIGINT */ + } + else + { /* 4. */ + JERRY_ASSERT (is_px_string && is_py_string); + + ecma_string_t *str_x_p = ecma_get_string_from_value (px); + ecma_string_t *str_y_p = ecma_get_string_from_value (py); + + bool is_px_less = ecma_compare_ecma_strings_relational (str_x_p, str_y_p); + + ret_value = ecma_make_boolean_value (is_px_less); + } + +end: + ecma_free_value (prim_second_converted_value); + ecma_free_value (prim_first_converted_value); + + return ret_value; +} /* ecma_op_abstract_relational_compare */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.h new file mode 100644 index 00000000..d8e0084e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-comparison.h @@ -0,0 +1,38 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_COMPARISON_H +#define ECMA_COMPARISON_H + +#include "ecma-globals.h" +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmacomparison ECMA comparison + * @{ + */ + +ecma_value_t ecma_op_abstract_equality_compare (ecma_value_t x, ecma_value_t y); +bool ecma_op_strict_equality_compare (ecma_value_t x, ecma_value_t y); +ecma_value_t ecma_op_abstract_relational_compare (ecma_value_t x, ecma_value_t y, bool left_first); + +/** + * @} + * @} + */ + +#endif /* !ECMA_COMPARISON_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.cpp new file mode 100644 index 00000000..bc602f96 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.cpp @@ -0,0 +1,1143 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ecma-container-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-property-hashmap.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_CONTAINER + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup \addtogroup ecmamaphelpers ECMA builtin Map/Set helper functions + * @{ + */ + +/** + * Create a new internal buffer. + * + * Note: + * The first element of the collection tracks the size of the buffer. + * ECMA_VALUE_EMPTY values are not calculated into the size. + * + * @return pointer to the internal buffer + */ +static inline ecma_collection_t * +ecma_op_create_internal_buffer (void) +{ + ecma_collection_t *collection_p = ecma_new_collection (); + ecma_collection_push_back (collection_p, (ecma_value_t) 0); + + return collection_p; +} /* ecma_op_create_internal_buffer */ + +/** + * Append values to the internal buffer. + */ +static void +ecma_op_internal_buffer_append (ecma_collection_t *container_p, /**< internal container pointer */ + ecma_value_t key_arg, /**< key argument */ + ecma_value_t value_arg, /**< value argument */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (container_p != NULL); + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_value_t values[] = { ecma_copy_value_if_not_object (key_arg), ecma_copy_value_if_not_object (value_arg) }; + ecma_collection_append (container_p, values, 2); + } + else + { + ecma_collection_push_back (container_p, ecma_copy_value_if_not_object (key_arg)); + } + + ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) + 1); +} /* ecma_op_internal_buffer_append */ + +/** + * Update the value of a given entry. + */ +static inline void +ecma_op_internal_buffer_update (ecma_value_t *entry_p, /**< entry pointer */ + ecma_value_t value_arg, /**< value argument */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (entry_p != NULL); + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_free_value_if_not_object (((ecma_container_pair_t *) entry_p)->value); + + ((ecma_container_pair_t *) entry_p)->value = ecma_copy_value_if_not_object (value_arg); + } +} /* ecma_op_internal_buffer_update */ + +/** + * Delete element from the internal buffer. + */ +static void +ecma_op_internal_buffer_delete (ecma_collection_t *container_p, /**< internal container pointer */ + ecma_container_pair_t *entry_p, /**< entry pointer */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (container_p != NULL); + JERRY_ASSERT (entry_p != NULL); + + ecma_free_value_if_not_object (entry_p->key); + entry_p->key = ECMA_VALUE_EMPTY; + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + ecma_free_value_if_not_object (entry_p->value); + entry_p->value = ECMA_VALUE_EMPTY; + } + + ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) - 1); +} /* ecma_op_internal_buffer_delete */ + +/** + * Find an entry in the collection. + * + * @return pointer to the appropriate entry. + */ +static ecma_value_t * +ecma_op_internal_buffer_find (ecma_collection_t *container_p, /**< internal container pointer */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (container_p != NULL); + + uint8_t entry_size = ecma_op_container_entry_size (lit_id); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += entry_size) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_op_same_value_zero (*entry_p, key_arg, false)) + { + return entry_p; + } + } + + return NULL; +} /* ecma_op_internal_buffer_find */ + +/** + * Get the value that belongs to the key. + * + * Note: in case of Set containers, the values are the same as the keys. + * + * @return ecma value + */ +static ecma_value_t +ecma_op_container_get_value (ecma_value_t *entry_p, /**< entry (key) pointer */ + lit_magic_string_id_t lit_id) /**< class id */ +{ + JERRY_ASSERT (entry_p != NULL); + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + return ((ecma_container_pair_t *) entry_p)->value; + } + + return *entry_p; +} /* ecma_op_container_get_value */ + +/** + * Get the size (in ecma_value_t) of the stored entries. + * + * @return size of the entries. + */ +uint8_t +ecma_op_container_entry_size (lit_magic_string_id_t lit_id) /**< class id */ +{ + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) + { + return ECMA_CONTAINER_PAIR_SIZE; + } + + return ECMA_CONTAINER_VALUE_SIZE; +} /* ecma_op_container_entry_size */ + +/** + * Release the entries in the WeakSet container. + */ +static void +ecma_op_container_free_weakset_entries (ecma_object_t *object_p, /**< object pointer */ + ecma_collection_t *container_p) /** internal buffer pointer */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + ecma_op_object_unref_weak (ecma_get_object_from_value (*entry_p), ecma_make_object_value (object_p)); + ecma_op_container_remove_weak_entry (object_p, *entry_p); + + *entry_p = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_weakset_entries */ + +/** + * Release the entries in the WeakMap container. + */ +static void +ecma_op_container_free_weakmap_entries (ecma_object_t *object_p, /**< object pointer */ + ecma_collection_t *container_p) /**< internal buffer pointer */ +{ + JERRY_ASSERT (object_p != NULL); + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + ecma_op_object_unref_weak (ecma_get_object_from_value (entry_p->key), ecma_make_object_value (object_p)); + ecma_op_container_remove_weak_entry (object_p, entry_p->key); + + ecma_free_value_if_not_object (entry_p->value); + + entry_p->key = ECMA_VALUE_EMPTY; + entry_p->value = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_weakmap_entries */ + +/** + * Release the entries in the Set container. + */ +static void +ecma_op_container_free_set_entries (ecma_collection_t *container_p) +{ + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + ecma_free_value_if_not_object (*entry_p); + *entry_p = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_set_entries */ + +/** + * Release the entries in the Map container. + */ +static void +ecma_op_container_free_map_entries (ecma_collection_t *container_p) +{ + JERRY_ASSERT (container_p != NULL); + + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + + for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) + { + ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); + + if (ecma_is_value_empty (entry_p->key)) + { + continue; + } + + ecma_free_value_if_not_object (entry_p->key); + ecma_free_value_if_not_object (entry_p->value); + + entry_p->key = ECMA_VALUE_EMPTY; + entry_p->value = ECMA_VALUE_EMPTY; + } +} /* ecma_op_container_free_map_entries */ + +/** + * Release the internal buffer and the stored entries. + */ +void +ecma_op_container_free_entries (ecma_object_t *object_p) /**< collection object pointer */ +{ + JERRY_ASSERT (object_p != NULL); + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + switch (map_object_p->u.cls.u2.container_id) + { + case LIT_MAGIC_STRING_WEAKSET_UL: + { + ecma_op_container_free_weakset_entries (object_p, container_p); + break; + } + case LIT_MAGIC_STRING_WEAKMAP_UL: + { + ecma_op_container_free_weakmap_entries (object_p, container_p); + break; + } + case LIT_MAGIC_STRING_SET_UL: + { + ecma_op_container_free_set_entries (container_p); + break; + } + case LIT_MAGIC_STRING_MAP_UL: + { + ecma_op_container_free_map_entries (container_p); + break; + } + default: + { + break; + } + } + + ECMA_CONTAINER_SET_SIZE (container_p, 0); +} /* ecma_op_container_free_entries */ + +/** + * Handle calling [[Construct]] of built-in Map/Set like objects + * + * @return ecma value + */ +ecma_value_t +ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len, /**< number of arguments */ + lit_magic_string_id_t lit_id, /**< internal class id */ + ecma_builtin_id_t proto_id) /**< prototype builtin id */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + JERRY_ASSERT (lit_id == LIT_MAGIC_STRING_MAP_UL || lit_id == LIT_MAGIC_STRING_SET_UL + || lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL); + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) != NULL); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), proto_id); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_collection_t *container_p = ecma_op_create_internal_buffer (); + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (proto_p); + ecma_extended_object_t *map_obj_p = (ecma_extended_object_t *) object_p; + map_obj_p->u.cls.type = ECMA_OBJECT_CLASS_CONTAINER; + map_obj_p->u.cls.u1.container_flags = ECMA_CONTAINER_FLAGS_EMPTY; + map_obj_p->u.cls.u2.container_id = (uint16_t) lit_id; + ecma_value_t iterator; + ecma_object_t *adder_func_p; + + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL) + { + map_obj_p->u.cls.u1.container_flags |= ECMA_CONTAINER_FLAGS_WEAK; + } + + ECMA_SET_INTERNAL_VALUE_POINTER (map_obj_p->u.cls.u3.value, container_p); + + ecma_value_t set_value = ecma_make_object_value (object_p); + ecma_value_t result = set_value; + + if (arguments_list_len == 0) + { + return result; + } + + ecma_value_t iterable = arguments_list_p[0]; + + if (ecma_is_value_undefined (iterable) || ecma_is_value_null (iterable)) + { + return result; + } + + lit_magic_string_id_t adder_string_id; + if (lit_id == LIT_MAGIC_STRING_MAP_UL || lit_id == LIT_MAGIC_STRING_WEAKMAP_UL) + { + adder_string_id = LIT_MAGIC_STRING_SET; + } + else + { + adder_string_id = LIT_MAGIC_STRING_ADD; + } + + result = ecma_op_object_get_by_magic_id (object_p, adder_string_id); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_object; + } + + if (!ecma_op_is_callable (result)) + { + ecma_free_value (result); + result = ecma_raise_type_error (ECMA_ERR_FUNCTION_ADD_ORSET_IS_NOT_CALLABLE); + goto cleanup_object; + } + + adder_func_p = ecma_get_object_from_value (result); + + ecma_value_t next_method; + result = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_adder; + } + + iterator = result; + + while (true) + { + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + if (ecma_is_value_false (result)) + { + break; + } + + const ecma_value_t next = result; + result = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_iterator; + } + + if (lit_id == LIT_MAGIC_STRING_SET_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL) + { + const ecma_value_t value = result; + + ecma_value_t arguments[] = { value }; + result = ecma_op_function_call (adder_func_p, set_value, arguments, 1); + + ecma_free_value (value); + } + else + { + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + ecma_raise_type_error (ECMA_ERR_ITERATOR_VALUE_IS_NOT_AN_OBJECT); + result = ecma_op_iterator_close (iterator); + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + goto cleanup_iterator; + } + + ecma_object_t *next_object_p = ecma_get_object_from_value (result); + + result = ecma_op_object_get_by_index (next_object_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_op_iterator_close (iterator); + goto cleanup_iterator; + } + + const ecma_value_t key = result; + + result = ecma_op_object_get_by_index (next_object_p, 1); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (next_object_p); + ecma_free_value (key); + ecma_op_iterator_close (iterator); + goto cleanup_iterator; + } + + const ecma_value_t value = result; + ecma_value_t arguments[] = { key, value }; + result = ecma_op_function_call (adder_func_p, set_value, arguments, 2); + + ecma_free_value (key); + ecma_free_value (value); + ecma_deref_object (next_object_p); + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_op_iterator_close (iterator); + goto cleanup_iterator; + } + + ecma_free_value (result); + } + + ecma_ref_object (object_p); + result = ecma_make_object_value (object_p); + +cleanup_iterator: + ecma_free_value (iterator); + ecma_free_value (next_method); +cleanup_adder: + ecma_deref_object (adder_func_p); +cleanup_object: + ecma_deref_object (object_p); + + return result; +} /* ecma_op_container_create */ + +/** + * Get Map/Set object pointer + * + * Note: + * If the function returns with NULL, the error object has + * already set, and the caller must return with ECMA_VALUE_ERROR + * + * @return pointer to the Map/Set if this_arg is a valid Map/Set object + * NULL otherwise + */ +ecma_extended_object_t * +ecma_op_container_get_object (ecma_value_t this_arg, /**< this argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *map_object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (map_object_p, ECMA_OBJECT_CLASS_CONTAINER) + && ((ecma_extended_object_t *) map_object_p)->u.cls.u2.container_id == lit_id) + { + return (ecma_extended_object_t *) map_object_p; + } + } + +#if JERRY_ERROR_MESSAGES + ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, + "Expected a % object", + ecma_make_string_value (ecma_get_magic_string (lit_id))); +#else /* !JERRY_ERROR_MESSAGES */ + ecma_raise_type_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + + return NULL; +} /* ecma_op_container_get_object */ + +/** + * Returns with the size of the Map/Set object. + * + * @return size of the Map/Set object as ecma-value. + */ +ecma_value_t +ecma_op_container_size (ecma_extended_object_t *map_object_p) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + return ecma_make_uint32_value (ECMA_CONTAINER_GET_SIZE (container_p)); +} /* ecma_op_container_size */ + +/** + * The generic Map/WeakMap prototype object's 'get' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_get (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL && !ecma_is_value_object (key_arg)) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + if (ECMA_CONTAINER_GET_SIZE (container_p) == 0) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_copy_value (((ecma_container_pair_t *) entry_p)->value); +} /* ecma_op_container_get */ + +/** + * The generic Map/Set prototype object's 'has' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_has (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + if ((map_object_p->u.cls.u1.container_flags & ECMA_CONTAINER_FLAGS_WEAK) != 0 && !ecma_is_value_object (key_arg)) + { + return ECMA_VALUE_FALSE; + } + + if (ECMA_CONTAINER_GET_SIZE (container_p) == 0) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + return ecma_make_boolean_value (entry_p != NULL); +} /* ecma_op_container_has */ + +/** + * Helper method for the Map.prototype.set and Set.prototype.add methods to swap the sign of the given value if needed + * + * See also: + * ECMA-262 v6, 23.2.3.1 step 6 + * ECMA-262 v6, 23.1.3.9 step 6 + * + * @return ecma value + */ +static ecma_value_t +ecma_op_container_set_noramlize_zero (ecma_value_t this_arg) /*< this arg */ +{ + if (ecma_is_value_number (this_arg)) + { + ecma_number_t number_value = ecma_get_number_from_value (this_arg); + + if (JERRY_UNLIKELY (ecma_number_is_zero (number_value) && ecma_number_is_negative (number_value))) + { + return ecma_make_integer_value (0); + } + } + + return this_arg; +} /* ecma_op_container_set_noramlize_zero */ + +/** + * The generic Map prototype object's 'set' and Set prototype object's 'add' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_set (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + ecma_value_t value_arg, /**< value argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + if ((map_object_p->u.cls.u1.container_flags & ECMA_CONTAINER_FLAGS_WEAK) != 0 && !ecma_is_value_object (key_arg)) + { + return ecma_raise_type_error (ECMA_ERR_KEY_MUST_BE_AN_OBJECT); + } + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + ecma_op_internal_buffer_append (container_p, ecma_op_container_set_noramlize_zero (key_arg), value_arg, lit_id); + + if ((map_object_p->u.cls.u1.container_flags & ECMA_CONTAINER_FLAGS_WEAK) != 0) + { + ecma_object_t *key_p = ecma_get_object_from_value (key_arg); + ecma_op_object_set_weak (key_p, (ecma_object_t *) map_object_p); + } + } + else + { + ecma_op_internal_buffer_update (entry_p, ecma_op_container_set_noramlize_zero (value_arg), lit_id); + } + + ecma_ref_object ((ecma_object_t *) map_object_p); + return ecma_make_object_value ((ecma_object_t *) map_object_p); +} /* ecma_op_container_set */ + +/** + * The generic Map/Set prototype object's 'forEach' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_foreach (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t predicate, /**< callback function */ + ecma_value_t predicate_this_arg, /**< this argument for + * invoke predicate */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (!ecma_op_is_callable (predicate)) + { + return ecma_raise_type_error (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE); + } + + JERRY_ASSERT (ecma_is_value_object (predicate)); + ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); + ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + uint8_t entry_size = ecma_op_container_entry_size (lit_id); + + for (uint32_t i = 0; i < ECMA_CONTAINER_ENTRY_COUNT (container_p); i += entry_size) + { + ecma_value_t *entry_p = ECMA_CONTAINER_START (container_p) + i; + + if (ecma_is_value_empty (*entry_p)) + { + continue; + } + + ecma_value_t key_arg = *entry_p; + ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id); + + ecma_value_t this_arg = ecma_make_object_value ((ecma_object_t *) map_object_p); + ecma_value_t call_args[] = { value_arg, key_arg, this_arg }; + ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + ret_value = call_value; + break; + } + + ecma_free_value (call_value); + } + + return ret_value; +} /* ecma_op_container_foreach */ + +/** + * The Map/Set prototype object's 'clear' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_clear (ecma_extended_object_t *map_object_p) /**< this argument */ +{ + ecma_op_container_free_entries ((ecma_object_t *) map_object_p); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_container_clear */ + +/** + * The generic Map/Set prototype object's 'delete' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_delete (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + return ECMA_VALUE_FALSE; + } + + ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id); + return ECMA_VALUE_TRUE; +} /* ecma_op_container_delete */ + +/** + * The generic WeakMap/WeakSet prototype object's 'delete' routine + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_container_delete_weak (ecma_extended_object_t *map_object_p, /**< map object */ + ecma_value_t key_arg, /**< key argument */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + if (!ecma_is_value_object (key_arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); + + if (entry_p == NULL) + { + return ECMA_VALUE_FALSE; + } + + ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id); + + ecma_object_t *key_object_p = ecma_get_object_from_value (key_arg); + ecma_op_object_unref_weak (key_object_p, ecma_make_object_value ((ecma_object_t *) map_object_p)); + + return ECMA_VALUE_TRUE; +} /* ecma_op_container_delete_weak */ + +/** + * Helper function to get the value from a weak container object + * + * @return value property + */ +ecma_value_t +ecma_op_container_find_weak_value (ecma_object_t *object_p, /**< internal container object */ + ecma_value_t key_arg) /**< key */ +{ + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (map_object_p->u.cls.type == ECMA_OBJECT_CLASS_CONTAINER + && map_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL); + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); + + JERRY_ASSERT (entry_p != NULL); + + return entry_p[1]; +} /* ecma_op_container_find_weak_value */ + +/** + * Helper function to remove a key/value pair from a weak container object + */ +void +ecma_op_container_remove_weak_entry (ecma_object_t *object_p, /**< internal container object */ + ecma_value_t key_arg) /**< key */ +{ + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (map_object_p->u.cls.type == ECMA_OBJECT_CLASS_CONTAINER + && (map_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKSET_UL + || map_object_p->u.cls.u2.container_id == LIT_MAGIC_STRING_WEAKMAP_UL)); + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + + ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); + + JERRY_ASSERT (entry_p != NULL); + + ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id); +} /* ecma_op_container_remove_weak_entry */ + +/** + * The Create{Set, Map}Iterator Abstract operation + * + * See also: + * ECMA-262 v6, 23.1.5.1 + * ECMA-262 v6, 23.2.5.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return Map/Set iterator object, if success + * error - otherwise + */ +ecma_value_t +ecma_op_container_create_iterator (ecma_value_t this_arg, /**< this argument */ + ecma_builtin_id_t proto_id, /**< prototype builtin id */ + ecma_object_class_type_t iterator_type, /**< iterator type */ + ecma_iterator_kind_t kind) /**< iterator kind */ +{ + return ecma_op_create_iterator_object (this_arg, ecma_builtin_get (proto_id), iterator_type, kind); +} /* ecma_op_container_create_iterator */ + +/** + * Get the index of the iterator object. + * + * @return index of the iterator. + */ +static uint32_t +ecma_op_iterator_get_index (ecma_object_t *iter_obj_p) /**< iterator object pointer */ +{ + uint32_t index = ((ecma_extended_object_t *) iter_obj_p)->u.cls.u2.iterator_index; + + if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT)) + { + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p); + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + return (uint32_t) (ecma_get_number_from_value (value_p->value)); + } + + return index; +} /* ecma_op_iterator_get_index */ + +/** + * Set the index of the iterator object. + */ +static void +ecma_op_iterator_set_index (ecma_object_t *iter_obj_p, /**< iterator object pointer */ + uint32_t index) /* iterator index to set */ +{ + if (JERRY_UNLIKELY (index >= ECMA_ITERATOR_INDEX_LIMIT)) + { + /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] + property is stored as an internal property */ + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); + ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p); + ecma_property_value_t *value_p; + + if (property_p == NULL) + { + value_p = ecma_create_named_data_property (iter_obj_p, prop_name_p, ECMA_PROPERTY_FLAG_WRITABLE, &property_p); + value_p->value = ecma_make_uint32_value (index); + } + else + { + value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + value_p->value = ecma_make_uint32_value (index); + } + } + else + { + ((ecma_extended_object_t *) iter_obj_p)->u.cls.u2.iterator_index = (uint16_t) index; + } +} /* ecma_op_iterator_set_index */ + +/** + * The %{Set, Map}IteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 23.1.5.2.1 + * ECMA-262 v6, 23.2.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +ecma_value_t +ecma_op_container_iterator_next (ecma_value_t this_val, /**< this argument */ + ecma_object_class_type_t iterator_type) /**< type of the iterator */ +{ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + if (!ecma_object_class_is (obj_p, iterator_type)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR); + } + + ecma_value_t iterated_value = ext_obj_p->u.cls.u3.iterated_value; + + if (ecma_is_value_empty (iterated_value)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) (ecma_get_object_from_value (iterated_value)); + lit_magic_string_id_t lit_id = (lit_magic_string_id_t) map_object_p->u.cls.u2.container_id; + + ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, map_object_p->u.cls.u3.value); + uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); + uint32_t index = ecma_op_iterator_get_index (obj_p); + + if (index == entry_count) + { + ext_obj_p->u.cls.u3.iterated_value = ECMA_VALUE_EMPTY; + + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + uint8_t entry_size = ecma_op_container_entry_size (lit_id); + uint8_t iterator_kind = ext_obj_p->u.cls.u1.iterator_kind; + ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); + ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; + + for (uint32_t i = index; i < entry_count; i += entry_size) + { + ecma_value_t *entry_p = start_p + i; + + if (ecma_is_value_empty (*entry_p)) + { + if (i == (entry_count - entry_size)) + { + ret_value = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + break; + } + + continue; + } + + ecma_op_iterator_set_index (obj_p, i + entry_size); + + ecma_value_t key_arg = *entry_p; + ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id); + + if (iterator_kind == ECMA_ITERATOR_KEYS) + { + ret_value = ecma_create_iter_result_object (key_arg, ECMA_VALUE_FALSE); + } + else if (iterator_kind == ECMA_ITERATOR_VALUES) + { + ret_value = ecma_create_iter_result_object (value_arg, ECMA_VALUE_FALSE); + } + else + { + JERRY_ASSERT (iterator_kind == ECMA_ITERATOR_ENTRIES); + + ecma_value_t entry_array_value; + entry_array_value = ecma_create_array_from_iter_element (value_arg, key_arg); + + ret_value = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE); + ecma_free_value (entry_array_value); + } + + break; + } + + return ret_value; +} /* ecma_op_container_iterator_next */ + +/** + * Dispatcher of builtin container routines. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_container_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + lit_magic_string_id_t lit_id) /**< internal class id */ +{ + ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); + + if (map_object_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + switch (builtin_routine_id) + { + case ECMA_CONTAINER_ROUTINE_DELETE: + { + return ecma_op_container_delete (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_DELETE_WEAK: + { + return ecma_op_container_delete_weak (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_GET: + { + return ecma_op_container_get (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_SET: + { + return ecma_op_container_set (map_object_p, arguments_list_p[0], arguments_list_p[1], lit_id); + } + case ECMA_CONTAINER_ROUTINE_HAS: + { + return ecma_op_container_has (map_object_p, arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_FOREACH: + { + return ecma_op_container_foreach (map_object_p, arguments_list_p[0], arguments_list_p[1], lit_id); + } + case ECMA_CONTAINER_ROUTINE_SIZE_GETTER: + { + return ecma_op_container_size (map_object_p); + } + case ECMA_CONTAINER_ROUTINE_ADD: + { + return ecma_op_container_set (map_object_p, arguments_list_p[0], arguments_list_p[0], lit_id); + } + case ECMA_CONTAINER_ROUTINE_CLEAR: + { + return ecma_op_container_clear (map_object_p); + } + case ECMA_CONTAINER_ROUTINE_KEYS: + case ECMA_CONTAINER_ROUTINE_VALUES: + case ECMA_CONTAINER_ROUTINE_ENTRIES: + { + ecma_builtin_id_t builtin_iterator_prototype = ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE; + ecma_object_class_type_t iterator_type = ECMA_OBJECT_CLASS_MAP_ITERATOR; + + if (lit_id != LIT_MAGIC_STRING_MAP_UL) + { + builtin_iterator_prototype = ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE; + iterator_type = ECMA_OBJECT_CLASS_SET_ITERATOR; + } + + ecma_iterator_kind_t kind = (ecma_iterator_kind_t) (builtin_routine_id - ECMA_CONTAINER_ROUTINE_KEYS); + + return ecma_op_container_create_iterator (this_arg, builtin_iterator_prototype, iterator_type, kind); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_builtin_container_dispatch_routine */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.h new file mode 100644 index 00000000..92fc6eb2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-container-object.h @@ -0,0 +1,97 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_CONTAINER_OBJECT_H +#define ECMA_CONTAINER_OBJECT_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" + +#if JERRY_BUILTIN_CONTAINER + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmamaphelpers ECMA builtin map/set helper functions + * @{ + */ + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_CONTAINER_ROUTINE_START = 0, + ECMA_CONTAINER_ROUTINE_ADD, + ECMA_CONTAINER_ROUTINE_CLEAR, + ECMA_CONTAINER_ROUTINE_DELETE_WEAK, + ECMA_CONTAINER_ROUTINE_DELETE, + ECMA_CONTAINER_ROUTINE_FOREACH, + ECMA_CONTAINER_ROUTINE_HAS, + ECMA_CONTAINER_ROUTINE_SIZE_GETTER, + ECMA_CONTAINER_ROUTINE_GET, + ECMA_CONTAINER_ROUTINE_SET, + /* Note: These 3 routines MUST be in this order */ + ECMA_CONTAINER_ROUTINE_KEYS, + ECMA_CONTAINER_ROUTINE_VALUES, + ECMA_CONTAINER_ROUTINE_ENTRIES +}; + +uint8_t ecma_op_container_entry_size (lit_magic_string_id_t lit_id); +ecma_extended_object_t *ecma_op_container_get_object (ecma_value_t this_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_create (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + lit_magic_string_id_t lit_id, + ecma_builtin_id_t proto_id); +ecma_value_t ecma_op_container_size (ecma_extended_object_t *map_object_p); +ecma_value_t +ecma_op_container_get (ecma_extended_object_t *map_object_p, ecma_value_t key_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_foreach (ecma_extended_object_t *map_object_p, + ecma_value_t predicate, + ecma_value_t predicate_this_arg, + lit_magic_string_id_t lit_id); +ecma_value_t +ecma_op_container_has (ecma_extended_object_t *map_object_p, ecma_value_t key_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_set (ecma_extended_object_t *map_object_p, + ecma_value_t key_arg, + ecma_value_t value_arg, + lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_clear (ecma_extended_object_t *map_object_p); +ecma_value_t +ecma_op_container_delete (ecma_extended_object_t *map_object_p, ecma_value_t key_arg, lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_delete_weak (ecma_extended_object_t *map_object_p, + ecma_value_t key_arg, + lit_magic_string_id_t lit_id); +ecma_value_t ecma_op_container_find_weak_value (ecma_object_t *object_p, ecma_value_t key_arg); +void ecma_op_container_remove_weak_entry (ecma_object_t *object_p, ecma_value_t key_arg); +void ecma_op_container_free_entries (ecma_object_t *object_p); +ecma_value_t ecma_op_container_create_iterator (ecma_value_t this_arg, + ecma_builtin_id_t proto_id, + ecma_object_class_type_t iterator_type, + ecma_iterator_kind_t kind); +ecma_value_t ecma_op_container_iterator_next (ecma_value_t this_val, ecma_object_class_type_t iterator_type); +ecma_value_t ecma_builtin_container_dispatch_routine (uint16_t builtin_routine_id, + ecma_value_t this_arg, + const ecma_value_t arguments_list_p[], + lit_magic_string_id_t lit_id); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_CONTAINER */ + +#endif /* !ECMA_CONTAINER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.cpp new file mode 100644 index 00000000..68865ba4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.cpp @@ -0,0 +1,1082 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of ECMA-defined conversion routines + */ + +#include "ecma-conversion.h" + +#include + +#include "ecma-alloc.h" +#include "ecma-bigint-object.h" +#include "ecma-bigint.h" +#include "ecma-boolean-object.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-number-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-string-object.h" +#include "ecma-symbol-object.h" + +#include "jrt-libc-includes.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaconversion ECMA conversion routines + * @{ + */ + +/** + * RequireObjectCoercible operation. + * + * See also: + * ECMA-262 v11, 7.2.1 + * + * @return true - if the value can be coerced to object without any exceptions + * false - otherwise + */ +bool +ecma_op_require_object_coercible (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) + { + ecma_raise_type_error (ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT); + return false; + } + + return true; +} /* ecma_op_require_object_coercible */ + +/** + * SameValue operation. + * + * See also: + * ECMA-262 v5, 9.12 + * + * @return true - if the value are same according to ECMA-defined SameValue algorithm, + * false - otherwise + */ +bool +ecma_op_same_value (ecma_value_t x, /**< ecma value */ + ecma_value_t y) /**< ecma value */ +{ + if (x == y) + { + return true; + } + + ecma_type_t type_of_x = ecma_get_value_type_field (x); + + if (type_of_x != ecma_get_value_type_field (y) || type_of_x == ECMA_TYPE_DIRECT) + { + return false; + } + + if (ecma_is_value_number (x)) + { + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_nan = ecma_number_is_nan (x_num); + bool is_y_nan = ecma_number_is_nan (y_num); + + if (is_x_nan || is_y_nan) + { + return is_x_nan && is_y_nan; + } + + if (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num) + && ecma_number_is_negative (x_num) != ecma_number_is_negative (y_num)) + { + return false; + } + + return (x_num == y_num); + } + + if (ecma_is_value_string (x)) + { + ecma_string_t *x_str_p = ecma_get_string_from_value (x); + ecma_string_t *y_str_p = ecma_get_string_from_value (y); + + return ecma_compare_ecma_strings (x_str_p, y_str_p); + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (x)) + { + return (ecma_is_value_bigint (y) && ecma_bigint_compare_to_bigint (x, y) == 0); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (x) || ecma_is_value_symbol (x)); + + return false; +} /* ecma_op_same_value */ + +#if JERRY_BUILTIN_CONTAINER +/** + * SameValueZero operation. + * + * See also: + * ECMA-262 v6, 7.2.10 + * + * @return true - if the value are same according to ECMA-defined SameValueZero algorithm, + * false - otherwise + */ +bool +ecma_op_same_value_zero (ecma_value_t x, /**< ecma value */ + ecma_value_t y, /**< ecma value */ + bool strict_equality) /**< strict equality */ +{ + if (ecma_is_value_number (x) && ecma_is_value_number (y)) + { + ecma_number_t x_num = ecma_get_number_from_value (x); + ecma_number_t y_num = ecma_get_number_from_value (y); + + bool is_x_nan = ecma_number_is_nan (x_num); + bool is_y_nan = ecma_number_is_nan (y_num); + + if (strict_equality && is_x_nan && is_y_nan) + { + return false; + } + + if (is_x_nan || is_y_nan) + { + return (is_x_nan && is_y_nan); + } + + if (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num) + && ecma_number_is_negative (x_num) != ecma_number_is_negative (y_num)) + { + return true; + } + + return (x_num == y_num); + } + + return ecma_op_same_value (x, y); +} /* ecma_op_same_value_zero */ +#endif /* JERRY_BUILTIN_CONTAINER */ + +/** + * ToPrimitive operation. + * + * See also: + * ECMA-262 v5, 9.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_primitive (ecma_value_t value, /**< ecma value */ + ecma_preferred_type_hint_t preferred_type) /**< preferred type hint */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_object (value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + return ecma_op_object_default_value (obj_p, preferred_type); + } + else + { + return ecma_copy_value (value); + } +} /* ecma_op_to_primitive */ + +/** + * ToBoolean operation. Cannot throw an exception. + * + * See also: + * ECMA-262 v5, 9.2 + * + * @return true - if the logical value is true + * false - otherwise + */ +bool +ecma_op_to_boolean (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_simple (value)) + { + JERRY_ASSERT (ecma_is_value_boolean (value) || ecma_is_value_undefined (value) || ecma_is_value_null (value)); + + return ecma_is_value_true (value); + } + + if (ecma_is_value_integer_number (value)) + { + return (value != ecma_make_integer_value (0)); + } + + if (ecma_is_value_float_number (value)) + { + ecma_number_t num = ecma_get_float_from_value (value); + + return (!ecma_number_is_nan (num) && !ecma_number_is_zero (num)); + } + + if (ecma_is_value_string (value)) + { + ecma_string_t *str_p = ecma_get_string_from_value (value); + + return !ecma_string_is_empty (str_p); + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (value)) + { + return value != ECMA_BIGINT_ZERO; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (value) || ecma_is_value_symbol (value)); + + return true; +} /* ecma_op_to_boolean */ + +/** + * ToNumber operation. + * + * See also: + * ECMA-262 v5, 9.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_number (ecma_value_t value, /**< ecma value */ + ecma_number_t *number_p) /**< [out] ecma number */ +{ + return ecma_op_to_numeric (value, number_p, ECMA_TO_NUMERIC_NO_OPTS); +} /* ecma_op_to_number */ + +/** + * Helper to get the numeric value of an ecma value + * + * See also: + * ECMA-262 v11, 7.1.3 + * + * @return ECMA_VALUE_EMPTY if converted to number, BigInt if + * converted to BigInt, and conversion error otherwise + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_numeric (ecma_value_t value, /**< ecma value */ + ecma_number_t *number_p, /**< [out] ecma number */ + ecma_to_numeric_options_t options) /**< option bits */ +{ + JERRY_UNUSED (options); + + if (ecma_is_value_integer_number (value)) + { + *number_p = (ecma_number_t) ecma_get_integer_from_value (value); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_float_number (value)) + { + *number_p = ecma_get_float_from_value (value); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_string (value)) + { + ecma_string_t *str_p = ecma_get_string_from_value (value); + *number_p = ecma_string_to_number (str_p); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_undefined (value)) + { + *number_p = ecma_number_make_nan (); + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_null (value)) + { + *number_p = 0; + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_true (value)) + { + *number_p = 1; + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_false (value)) + { + *number_p = 0; + return ECMA_VALUE_EMPTY; + } + + if (ecma_is_value_symbol (value)) + { + return ecma_raise_type_error (ECMA_ERR_CONVERT_SYMBOL_TO_NUMBER); + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (value)) + { + if (options & ECMA_TO_NUMERIC_ALLOW_BIGINT) + { + return ecma_copy_value (value); + } + return ecma_raise_type_error (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (value)); + + ecma_object_t *object_p = ecma_get_object_from_value (value); + + ecma_value_t def_value = ecma_op_object_default_value (object_p, ECMA_PREFERRED_TYPE_NUMBER); + + if (ECMA_IS_VALUE_ERROR (def_value)) + { + return def_value; + } + + ecma_value_t ret_value = ecma_op_to_numeric (def_value, number_p, options); + + ecma_fast_free_value (def_value); + + return ret_value; +} /* ecma_op_to_numeric */ + +/** + * ToString operation. + * + * See also: + * ECMA-262 v5, 9.8 + * + * @return NULL - if the conversion fails + * pointer to the string descriptor - otherwise + */ +ecma_string_t * +ecma_op_to_string (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (ecma_is_value_string (value)) + { + ecma_string_t *res_p = ecma_get_string_from_value (value); + ecma_ref_ecma_string (res_p); + return res_p; + } + + if (ecma_is_value_integer_number (value)) + { + ecma_integer_value_t num = ecma_get_integer_from_value (value); + + if (num < 0) + { + return ecma_new_ecma_string_from_number ((ecma_number_t) num); + } + else + { + return ecma_new_ecma_string_from_uint32 ((uint32_t) num); + } + } + + if (ecma_is_value_float_number (value)) + { + ecma_number_t num = ecma_get_float_from_value (value); + return ecma_new_ecma_string_from_number (num); + } + + if (ecma_is_value_undefined (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); + } + + if (ecma_is_value_null (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_NULL); + } + + if (ecma_is_value_true (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); + } + + if (ecma_is_value_false (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); + } + + if (ecma_is_value_symbol (value)) + { + ecma_raise_type_error (ECMA_ERR_CONVERT_SYMBOL_TO_STRING); + return NULL; + } + +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (value)) + { + return ecma_bigint_to_string (value, 10); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + JERRY_ASSERT (ecma_is_value_object (value)); + + ecma_object_t *obj_p = ecma_get_object_from_value (value); + + ecma_value_t def_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_STRING); + + if (ECMA_IS_VALUE_ERROR (def_value)) + { + return NULL; + } + + ecma_string_t *ret_string_p = ecma_op_to_string (def_value); + + ecma_free_value (def_value); + + return ret_string_p; +} /* ecma_op_to_string */ + +/** + * ToPropertyKey operation. + * + * See also: + * ECMA 262 v6, 7.1.14 + * ECMA 262 v10, 7.1.14 + * ECMA 262 v11, 7.1.19 + * + * @return NULL - if the conversion fails + * ecma-string - otherwise + */ +ecma_string_t * +ecma_op_to_property_key (ecma_value_t value) /**< ecma value */ +{ + /* Fast path for strings and symbols */ + if (JERRY_LIKELY (ecma_is_value_prop_name (value))) + { + ecma_string_t *key_p = ecma_get_prop_name_from_value (value); + ecma_ref_ecma_string (key_p); + return key_p; + } + + ecma_value_t key = ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING); + + if (ECMA_IS_VALUE_ERROR (key)) + { + return NULL; + } + + if (ecma_is_value_symbol (key)) + { + ecma_string_t *symbol_p = ecma_get_symbol_from_value (key); + return symbol_p; + } + + ecma_string_t *result = ecma_op_to_string (key); + ecma_free_value (key); + + return result; +} /* ecma_op_to_property_key */ + +/** + * ToObject operation. + * + * See also: + * ECMA-262 v5, 9.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_to_object (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + ecma_builtin_id_t proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; + uint8_t class_type; + + if (ecma_is_value_number (value)) + { +#if JERRY_BUILTIN_NUMBER + proto_id = ECMA_BUILTIN_ID_NUMBER_PROTOTYPE; +#endif /* JERRY_BUILTIN_NUMBER */ + class_type = ECMA_OBJECT_CLASS_NUMBER; + } + else if (ecma_is_value_string (value)) + { +#if JERRY_BUILTIN_STRING + proto_id = ECMA_BUILTIN_ID_STRING_PROTOTYPE; +#endif /* JERRY_BUILTIN_STRING */ + class_type = ECMA_OBJECT_CLASS_STRING; + } + else if (ecma_is_value_object (value)) + { + return ecma_copy_value (value); + } + else if (ecma_is_value_symbol (value)) + { + proto_id = ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE; + class_type = ECMA_OBJECT_CLASS_SYMBOL; + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (value)) + { + return ecma_op_create_bigint_object (value); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + if (ecma_is_value_undefined (value) || ecma_is_value_null (value)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT); + } + else + { + JERRY_ASSERT (ecma_is_value_boolean (value)); +#if JERRY_BUILTIN_BOOLEAN + proto_id = ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE; +#endif /* JERRY_BUILTIN_BOOLEAN */ + class_type = ECMA_OBJECT_CLASS_BOOLEAN; + } + } + + ecma_object_t *object_p = + ecma_create_object (ecma_builtin_get (proto_id), sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = class_type; + ext_object_p->u.cls.u3.value = ecma_copy_value_if_not_object (value); + + return ecma_make_object_value (object_p); +} /* ecma_op_to_object */ + +/** + * FromPropertyDescriptor operation. + * + * See also: + * ECMA-262 v5, 8.10.4 + * + * @return constructed object + */ +ecma_object_t * +ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p) /**< property descriptor */ +{ + /* 2. */ + ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); + + ecma_value_t completion; + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + { + prop_desc.flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE + | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE + | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE); + } + + /* 3. */ + if (src_prop_desc_p->flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + { + JERRY_ASSERT ((prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + == (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)); + + /* a. */ + prop_desc.value = src_prop_desc_p->value; + + completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + /* b. */ + prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_WRITABLE); + + completion = + ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + } + else if (src_prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + /* a. */ + if (src_prop_desc_p->get_p == NULL) + { + prop_desc.value = ECMA_VALUE_UNDEFINED; + } + else + { + prop_desc.value = ecma_make_object_value (src_prop_desc_p->get_p); + } + + completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + /* b. */ + if (src_prop_desc_p->set_p == NULL) + { + prop_desc.value = ECMA_VALUE_UNDEFINED; + } + else + { + prop_desc.value = ecma_make_object_value (src_prop_desc_p->set_p); + } + + completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + } + + prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_ENUMERABLE); + + completion = + ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE); + + completion = + ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE), &prop_desc); + JERRY_ASSERT (ecma_is_value_true (completion)); + + return obj_p; +} /* ecma_op_from_property_descriptor */ + +/** + * ToPropertyDescriptor operation. + * + * See also: + * ECMA-262 v5, 8.10.5 + * + * @return ECMA_VALUE_EMPTY if successful, ECMA_VALUE_ERROR otherwise + */ +ecma_value_t +ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ + ecma_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor + * if the operation is successful, + * unmodified otherwise */ +{ + /* 1. */ + if (!ecma_is_value_object (obj_value)) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_value_t set_prop_value; + ecma_value_t get_prop_value; + ecma_value_t writable_prop_value; + ecma_value_t value_prop_value; + ecma_value_t configurable_prop_value; + ecma_property_descriptor_t prop_desc; + ecma_value_t enumerable_prop_value; + + /* 3. */ + enumerable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE)); + + if (ECMA_IS_VALUE_ERROR (enumerable_prop_value)) + { + return enumerable_prop_value; + } + + /* 2. */ + prop_desc = ecma_make_empty_property_descriptor (); + + if (ecma_is_value_found (enumerable_prop_value)) + { + uint32_t is_enumerable = + (ecma_op_to_boolean (enumerable_prop_value) ? JERRY_PROP_IS_ENUMERABLE : JERRY_PROP_NO_OPTS); + + prop_desc.flags |= (uint16_t) (JERRY_PROP_IS_ENUMERABLE_DEFINED | is_enumerable); + + ecma_free_value (enumerable_prop_value); + } + + /* 4. */ + configurable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE)); + + if (ECMA_IS_VALUE_ERROR (configurable_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (configurable_prop_value)) + { + uint32_t is_configurable = + (ecma_op_to_boolean (configurable_prop_value) ? JERRY_PROP_IS_CONFIGURABLE : JERRY_PROP_NO_OPTS); + + prop_desc.flags |= (uint16_t) (JERRY_PROP_IS_CONFIGURABLE_DEFINED | is_configurable); + + ecma_free_value (configurable_prop_value); + } + + /* 5. */ + value_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE)); + + if (ECMA_IS_VALUE_ERROR (value_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (value_prop_value)) + { + prop_desc.flags |= JERRY_PROP_IS_VALUE_DEFINED; + prop_desc.value = ecma_copy_value (value_prop_value); + ecma_free_value (value_prop_value); + } + + /* 6. */ + writable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE)); + + if (ECMA_IS_VALUE_ERROR (writable_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (writable_prop_value)) + { + uint32_t is_writable = (ecma_op_to_boolean (writable_prop_value) ? JERRY_PROP_IS_WRITABLE : JERRY_PROP_NO_OPTS); + + prop_desc.flags |= (uint16_t) (JERRY_PROP_IS_WRITABLE_DEFINED | is_writable); + + ecma_free_value (writable_prop_value); + } + + /* 7. */ + get_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET)); + + if (ECMA_IS_VALUE_ERROR (get_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (get_prop_value)) + { + if (!ecma_op_is_callable (get_prop_value) && !ecma_is_value_undefined (get_prop_value)) + { + ecma_free_value (get_prop_value); + ret_value = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + goto free_desc; + } + + prop_desc.flags |= JERRY_PROP_IS_GET_DEFINED; + + if (ecma_is_value_undefined (get_prop_value)) + { + prop_desc.get_p = NULL; + } + else + { + JERRY_ASSERT (ecma_is_value_object (get_prop_value)); + + ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value); + ecma_ref_object (get_p); + + prop_desc.get_p = get_p; + } + + ecma_free_value (get_prop_value); + } + + /* 8. */ + set_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET)); + + if (ECMA_IS_VALUE_ERROR (set_prop_value)) + { + goto free_desc; + } + + if (ecma_is_value_found (set_prop_value)) + { + if (!ecma_op_is_callable (set_prop_value) && !ecma_is_value_undefined (set_prop_value)) + { + ecma_free_value (set_prop_value); + ret_value = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + goto free_desc; + } + + prop_desc.flags |= JERRY_PROP_IS_SET_DEFINED; + + if (ecma_is_value_undefined (set_prop_value)) + { + prop_desc.set_p = NULL; + } + else + { + JERRY_ASSERT (ecma_is_value_object (set_prop_value)); + + ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value); + ecma_ref_object (set_p); + + prop_desc.set_p = set_p; + } + + ecma_free_value (set_prop_value); + } + + /* 9. */ + if ((prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + && (prop_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))) + { + ret_value = ecma_raise_type_error (ECMA_ERR_ACCESSOR_WRITABLE); + } + else + { + *out_prop_desc_p = prop_desc; + ret_value = ECMA_VALUE_EMPTY; + } + +free_desc: + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_free_property_descriptor (&prop_desc); + } + + return ret_value; +} /* ecma_op_to_property_descriptor */ + +/** + * IsInteger operation. + * + * See also: + * ECMA-262 v5, 9.4 + * ECMA-262 v6, 7.1.4 + * + * @return true - if the argument is integer + * false - otherwise + */ +bool +ecma_op_is_integer (ecma_number_t num) /**< ecma number */ +{ + if (ecma_number_is_nan (num) || ecma_number_is_infinity (num)) + { + return false; + } + + ecma_number_t floor_fabs = (ecma_number_t) floor (fabs (num)); + ecma_number_t fabs_value = (ecma_number_t) fabs (num); + + return (floor_fabs == fabs_value); +} /* ecma_op_is_integer */ + +/** + * ToInteger operation. + * + * See also: + * ECMA-262 v5, 9.4 + * ECMA-262 v6, 7.1.4 + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_op_to_integer (ecma_value_t value, /**< ecma value */ + ecma_number_t *number_p) /**< [out] ecma number */ +{ + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + /* 1 */ + ecma_value_t to_number = ecma_op_to_number (value, number_p); + + /* 2 */ + if (ECMA_IS_VALUE_ERROR (to_number)) + { + return to_number; + } + + ecma_number_t number = *number_p; + + /* 3 */ + if (ecma_number_is_nan (number)) + { + *number_p = ECMA_NUMBER_ZERO; + return ECMA_VALUE_EMPTY; + } + + /* 4 */ + if (ecma_number_is_zero (number) || ecma_number_is_infinity (number)) + { + return ECMA_VALUE_EMPTY; + } + + ecma_number_t floor_fabs = (ecma_number_t) floor (fabs (number)); + /* 5 */ + *number_p = ecma_number_is_negative (number) ? -floor_fabs : floor_fabs; + return ECMA_VALUE_EMPTY; +} /* ecma_op_to_integer */ + +/** + * ToLength operation. + * + * See also: + * ECMA-262 v6, 7.1.15 + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_op_to_length (ecma_value_t value, /**< ecma value */ + ecma_length_t *length) /**< [out] ecma number */ +{ + /* 1 */ + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + /* 2 */ + ecma_number_t num; + ecma_value_t length_num = ecma_op_to_integer (value, &num); + + /* 3 */ + if (ECMA_IS_VALUE_ERROR (length_num)) + { + return length_num; + } + + /* 4 */ + if (num <= 0.0f) + { + *length = 0; + return ECMA_VALUE_EMPTY; + } + + /* 5 */ + if (num >= ECMA_NUMBER_MAX_SAFE_INTEGER) + { + *length = (ecma_length_t) ECMA_NUMBER_MAX_SAFE_INTEGER; + return ECMA_VALUE_EMPTY; + } + + /* 6 */ + *length = (ecma_length_t) num; + return ECMA_VALUE_EMPTY; +} /* ecma_op_to_length */ + +/** + * ToIndex operation. + * + * See also: + * ECMA-262 v11, 7.1.22 + * + * @return ECMA_VALUE_EMPTY if successful + * conversion error otherwise + */ +ecma_value_t +ecma_op_to_index (ecma_value_t value, /**< ecma value */ + ecma_number_t *index) /**< [out] ecma number */ +{ + /* 1. */ + if (ecma_is_value_undefined (value)) + { + *index = 0; + return ECMA_VALUE_EMPTY; + } + + /* 2.a */ + ecma_number_t integer_index; + ecma_value_t index_value = ecma_op_to_integer (value, &integer_index); + + if (ECMA_IS_VALUE_ERROR (index_value)) + { + return index_value; + } + + /* 2.b - 2.d */ + if (integer_index < 0.0f || integer_index > ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OR_OUT_OF_RANGE_INDEX); + } + + /* 3. */ + *index = integer_index; + return ECMA_VALUE_EMPTY; +} /* ecma_op_to_index */ + +/** + * CreateListFromArrayLike operation. + * Different types are not handled yet. + * + * See also: + * ECMA-262 v6, 7.3.17 + * + * @return ecma_collection_t if successful + * NULL otherwise + */ +ecma_collection_t * +ecma_op_create_list_from_array_like (ecma_value_t arr, /**< array value */ + bool prop_names_only) /**< true - accept only property names + false - otherwise */ +{ + /* 1. */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (arr)); + + /* 3. */ + if (!ecma_is_value_object (arr)) + { + ecma_raise_type_error (ECMA_ERR_ARGUMENT_IS_NOT_AN_OBJECT); + return NULL; + } + ecma_object_t *obj_p = ecma_get_object_from_value (arr); + + /* 4. 5. */ + ecma_length_t len; + if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (obj_p, &len))) + { + return NULL; + } + + /* 6. */ + ecma_collection_t *list_ptr = ecma_new_collection (); + + /* 7. 8. */ + for (ecma_length_t idx = 0; idx < len; idx++) + { + ecma_value_t next = ecma_op_object_get_by_index (obj_p, idx); + if (ECMA_IS_VALUE_ERROR (next)) + { + ecma_collection_free (list_ptr); + return NULL; + } + + if (prop_names_only && !ecma_is_value_prop_name (next)) + { + ecma_free_value (next); + ecma_collection_free (list_ptr); + ecma_raise_type_error (ECMA_ERR_PROPERTY_NAME_IS_NEITHER_SYMBOL_NOR_STRING); + return NULL; + } + + ecma_collection_push_back (list_ptr, next); + } + + /* 9. */ + return list_ptr; +} /* ecma_op_create_list_from_array_like */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.h new file mode 100644 index 00000000..a19ade54 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-conversion.h @@ -0,0 +1,76 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_CONVERSION_H +#define ECMA_CONVERSION_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaconversion ECMA conversion routines + * @{ + */ + +/** + * Second argument of 'ToPrimitive' operation that is a hint, + * specifying the preferred type of conversion result. + */ +typedef enum +{ + ECMA_PREFERRED_TYPE_NO = 0, /**< no preferred type is specified */ + ECMA_PREFERRED_TYPE_NUMBER, /**< Number */ + ECMA_PREFERRED_TYPE_STRING /**< String */ +} ecma_preferred_type_hint_t; + +/** + * Option bits for ecma_op_to_numeric. + */ +typedef enum +{ + ECMA_TO_NUMERIC_NO_OPTS = 0, /**< no options (same as toNumber operation) */ + ECMA_TO_NUMERIC_ALLOW_BIGINT = (1 << 0), /**< allow BigInt values (ignored if BigInts are disabled) */ +} ecma_to_numeric_options_t; + +bool ecma_op_require_object_coercible (ecma_value_t value); +bool ecma_op_same_value (ecma_value_t x, ecma_value_t y); +#if JERRY_BUILTIN_CONTAINER +bool ecma_op_same_value_zero (ecma_value_t x, ecma_value_t y, bool strict_equality); +#endif /* JERRY_BUILTIN_CONTAINER */ +ecma_value_t ecma_op_to_primitive (ecma_value_t value, ecma_preferred_type_hint_t preferred_type); +bool ecma_op_to_boolean (ecma_value_t value); +ecma_value_t ecma_op_to_number (ecma_value_t value, ecma_number_t *number_p); +ecma_value_t ecma_op_to_numeric (ecma_value_t value, ecma_number_t *number_p, ecma_to_numeric_options_t options); +ecma_string_t *ecma_op_to_string (ecma_value_t value); +ecma_string_t *ecma_op_to_property_key (ecma_value_t value); +ecma_value_t ecma_op_to_object (ecma_value_t value); +bool ecma_op_is_integer (ecma_number_t value); +ecma_value_t ecma_op_to_integer (ecma_value_t value, ecma_number_t *number_p); +ecma_value_t ecma_op_to_length (ecma_value_t value, ecma_length_t *length); +ecma_value_t ecma_op_to_index (ecma_value_t value, ecma_number_t *index); +ecma_collection_t *ecma_op_create_list_from_array_like (ecma_value_t arr, bool prop_names_only); + +ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p); +ecma_value_t ecma_op_to_property_descriptor (ecma_value_t obj_value, ecma_property_descriptor_t *out_prop_desc_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_CONVERSION_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.cpp new file mode 100644 index 00000000..db2ae0a6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.cpp @@ -0,0 +1,409 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-dataview-object.h" + +#include "ecma-arraybuffer-object.h" +#include "ecma-bigint.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_DATAVIEW + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmadataviewobject ECMA builtin DataView helper functions + * @{ + */ + +/** + * Handle calling [[Construct]] of built-in DataView like objects + * + * See also: + * ECMA-262 v11, 24.3.2.1 + * + * @return created DataView object as an ecma-value - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_dataview_create (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p)); + + ecma_value_t buffer = arguments_list_len > 0 ? arguments_list_p[0] : ECMA_VALUE_UNDEFINED; + + /* 2. */ + if (!ecma_is_value_object (buffer)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_BUFFER_NOT_OBJECT); + } + + ecma_object_t *buffer_p = ecma_get_object_from_value (buffer); + + if (!(ecma_object_class_is (buffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (buffer_p))) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_BUFFER_NOT_ARRAY_OR_SHARED_BUFFER); + } + + /* 3. */ + ecma_number_t offset = 0; + + if (arguments_list_len > 1) + { + ecma_value_t offset_value = ecma_op_to_index (arguments_list_p[1], &offset); + if (ECMA_IS_VALUE_ERROR (offset_value)) + { + return offset_value; + } + } + + /* 4. */ + if (ecma_arraybuffer_is_detached (buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 5. */ + ecma_number_t buffer_byte_length = ecma_arraybuffer_get_length (buffer_p); + + /* 6. */ + if (offset > buffer_byte_length) + { + return ecma_raise_range_error (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER); + } + + /* 7. */ + uint32_t view_byte_length; + if (arguments_list_len > 2 && !ecma_is_value_undefined (arguments_list_p[2])) + { + /* 8.a */ + ecma_number_t byte_length_to_index; + ecma_value_t byte_length_value = ecma_op_to_index (arguments_list_p[2], &byte_length_to_index); + + if (ECMA_IS_VALUE_ERROR (byte_length_value)) + { + return byte_length_value; + } + + /* 8.b */ + if (offset + byte_length_to_index > buffer_byte_length) + { + return ecma_raise_range_error (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER); + } + + JERRY_ASSERT (byte_length_to_index <= UINT32_MAX); + view_byte_length = (uint32_t) byte_length_to_index; + } + else + { + /* 7.a */ + view_byte_length = (uint32_t) (buffer_byte_length - offset); + } + + /* 9. */ + ecma_object_t *prototype_obj_p = + ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 10. */ + if (ecma_arraybuffer_is_detached (buffer_p)) + { + ecma_deref_object (prototype_obj_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* 9. */ + /* It must happen after 10., because uninitialized object can't be destroyed properly. */ + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_dataview_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_deref_object (prototype_obj_p); + + /* 11 - 14. */ + ecma_dataview_object_t *dataview_obj_p = (ecma_dataview_object_t *) object_p; + dataview_obj_p->header.u.cls.type = ECMA_OBJECT_CLASS_DATAVIEW; + dataview_obj_p->header.u.cls.u3.length = view_byte_length; + dataview_obj_p->buffer_p = buffer_p; + dataview_obj_p->byte_offset = (uint32_t) offset; + + return ecma_make_object_value (object_p); +} /* ecma_op_dataview_create */ + +/** + * Get the DataView object pointer + * + * Note: + * If the function returns with NULL, the error object has + * already set, and the caller must return with ECMA_VALUE_ERROR + * + * @return pointer to the dataView if this_arg is a valid dataView object + * NULL otherwise + */ +ecma_dataview_object_t * +ecma_op_dataview_get_object (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_DATAVIEW)) + { + return (ecma_dataview_object_t *) object_p; + } + } + + ecma_raise_type_error (ECMA_ERR_EXPECTED_A_DATAVIEW_OBJECT); + return NULL; +} /* ecma_op_dataview_get_object */ + +/** + * Helper union to specify the system's endiannes + */ +typedef union +{ + uint32_t number; /**< for write numeric data */ + char data[sizeof (uint32_t)]; /**< for read numeric data */ +} ecma_dataview_endiannes_check_t; + +/** + * Helper function to check the current system endiannes + * + * @return true - if the current system has little endian byteorder + * false - otherwise + */ +static bool +ecma_dataview_check_little_endian (void) +{ + ecma_dataview_endiannes_check_t checker; + checker.number = 0x01; + + return checker.data[0] == 0x01; +} /* ecma_dataview_check_little_endian */ + +/** + * Helper function for swap bytes if the system's endiannes + * does not match with the requested endiannes. + */ +static void +ecma_dataview_swap_order (bool system_is_little_endian, /**< true - if the system has little endian byteorder + * false - otherwise */ + bool is_little_endian, /**< true - if little endian byteorder is requested + * false - otherwise */ + uint32_t element_size, /**< element size byte according to the Table 49.*/ + lit_utf8_byte_t *block_p) /**< data block */ +{ + if (system_is_little_endian ^ is_little_endian) + { + for (uint32_t i = 0; i < element_size / 2; i++) + { + lit_utf8_byte_t tmp = block_p[i]; + block_p[i] = block_p[element_size - i - 1]; + block_p[element_size - i - 1] = tmp; + } + } +} /* ecma_dataview_swap_order */ + +/** + * GetViewValue and SetViewValue abstact operation + * + * See also: + * ECMA-262 v11, 24.3.1.1 + * ECMA-262 v11, 24.3.1.2 + * + * @return ecma value + */ +ecma_value_t +ecma_op_dataview_get_set_view_value (ecma_value_t view, /**< the operation's 'view' argument */ + ecma_value_t request_index, /**< the operation's 'requestIndex' argument */ + ecma_value_t is_little_endian_value, /**< the operation's + * 'isLittleEndian' argument */ + ecma_value_t value_to_set, /**< the operation's 'value' argument */ + ecma_typedarray_type_t id) /**< the operation's 'type' argument */ +{ + /* 1 - 2. */ + ecma_dataview_object_t *view_p = ecma_op_dataview_get_object (view); + + if (JERRY_UNLIKELY (view_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *buffer_p = view_p->buffer_p; + JERRY_ASSERT (ecma_object_class_is (buffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) + || ecma_object_is_shared_arraybuffer (buffer_p)); + + /* 3. */ + ecma_number_t get_index; + ecma_value_t number_index_value = ecma_op_to_index (request_index, &get_index); + + if (ECMA_IS_VALUE_ERROR (number_index_value)) + { + return number_index_value; + } + + /* SetViewValue 4 - 5. */ + if (!ecma_is_value_empty (value_to_set)) + { +#if JERRY_BUILTIN_BIGINT + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (id)) + { + value_to_set = ecma_bigint_to_bigint (value_to_set, true); + + if (ECMA_IS_VALUE_ERROR (value_to_set)) + { + return value_to_set; + } + } + else +#endif /* JERRY_BUILTIN_BIGINT */ + { + ecma_number_t value_to_set_number; + ecma_value_t value = ecma_op_to_number (value_to_set, &value_to_set_number); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + value_to_set = ecma_make_number_value (value_to_set_number); + } + } + + /* GetViewValue 4., SetViewValue 6. */ + bool is_little_endian = ecma_op_to_boolean (is_little_endian_value); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (buffer_p)) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + ecma_free_value (value_to_set); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* GetViewValue 7., SetViewValue 9. */ + uint32_t view_offset = view_p->byte_offset; + + /* GetViewValue 8., SetViewValue 10. */ + uint32_t view_size = view_p->header.u.cls.u3.length; + + /* GetViewValue 9., SetViewValue 11. */ + uint8_t element_size = (uint8_t) (1 << (ecma_typedarray_helper_get_shift_size (id))); + + /* GetViewValue 10., SetViewValue 12. */ + if (get_index + element_size > (ecma_number_t) view_size) + { + ecma_free_value (value_to_set); + return ecma_raise_range_error (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER); + } + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (buffer_p)) + { + ecma_free_value (value_to_set); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (buffer_p)) + { + ecma_free_value (value_to_set); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + /* GetViewValue 11., SetViewValue 13. */ + bool system_is_little_endian = ecma_dataview_check_little_endian (); + + ecma_typedarray_info_t info; + info.id = id; + info.length = view_size; + info.shift = ecma_typedarray_helper_get_shift_size (id); + info.element_size = element_size; + info.offset = view_p->byte_offset; + info.array_buffer_p = buffer_p; + + /* GetViewValue 12. */ + uint8_t *block_p = ecma_arraybuffer_get_buffer (buffer_p) + (uint32_t) get_index + view_offset; + + if (ecma_is_value_empty (value_to_set)) + { + JERRY_VLA (lit_utf8_byte_t, swap_block_p, element_size); + memcpy (swap_block_p, block_p, element_size * sizeof (lit_utf8_byte_t)); + ecma_dataview_swap_order (system_is_little_endian, is_little_endian, element_size, swap_block_p); + + ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info.id); + return typedarray_getter_cb (swap_block_p); + } + + if (!ecma_number_is_nan (get_index) && get_index <= 0) + { + get_index = 0; + } + + /* SetViewValue 14. */ + ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info.id); + ecma_value_t set_element = typedarray_setter_cb (block_p, value_to_set); + + ecma_free_value (value_to_set); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + + ecma_dataview_swap_order (system_is_little_endian, is_little_endian, element_size, block_p); + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_dataview_get_set_view_value */ + +/** + * Check if the value is dataview + * + * @return true - if value is a DataView object + * false - otherwise + */ +bool +ecma_is_dataview (ecma_value_t value) /**< the target need to be checked */ +{ + if (!ecma_is_value_object (value)) + { + return false; + } + + return ecma_object_class_is (ecma_get_object_from_value (value), ECMA_OBJECT_CLASS_DATAVIEW); +} /* ecma_is_dataview */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.h new file mode 100644 index 00000000..1d56c9be --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-dataview-object.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_DATAVIEW_OBJECT_H +#define ECMA_DATAVIEW_OBJECT_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_DATAVIEW + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmadataviewobject ECMA builtin DataView helper functions + * @{ + */ + +ecma_value_t ecma_op_dataview_create (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); +ecma_dataview_object_t *ecma_op_dataview_get_object (ecma_value_t this_arg); +ecma_value_t ecma_op_dataview_get_set_view_value (ecma_value_t view, + ecma_value_t request_index, + ecma_value_t little_endian, + ecma_value_t value_to_set, + ecma_typedarray_type_t id); +bool ecma_is_dataview (ecma_value_t value); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_DATAVIEW */ + +#endif /* !ECMA_DATAVIEW_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.cpp new file mode 100644 index 00000000..ac8e2c40 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.cpp @@ -0,0 +1,100 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-eval.h" + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" + +#include "jcontext.h" +#include "js-parser.h" +#include "vm.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup eval eval + * @{ + */ + +/** + * Perform 'eval' with code stored in ecma-string + * + * See also: + * ecma_op_eval_chars_buffer + * ECMA-262 v5, 15.1.2.1 (steps 2 to 8) + * + * @return ecma value + */ +ecma_value_t +ecma_op_eval (ecma_value_t source_code, /**< source code */ + uint32_t parse_opts) /**< ecma_parse_opts_t option bits */ +{ + JERRY_ASSERT (ecma_is_value_string (source_code)); + + if (ecma_is_value_magic_string (source_code, LIT_MAGIC_STRING__EMPTY)) + { + return ECMA_VALUE_UNDEFINED; + } + + return ecma_op_eval_chars_buffer ((void *) &source_code, parse_opts | ECMA_PARSE_HAS_SOURCE_VALUE); +} /* ecma_op_eval */ + +/** + * Perform 'eval' with code stored in continuous character buffer + * + * See also: + * ecma_op_eval + * ECMA-262 v5, 15.1.2.1 (steps 2 to 8) + * + * @return ecma value + */ +ecma_value_t +ecma_op_eval_chars_buffer (void *source_p, /**< source code */ + uint32_t parse_opts) /**< ecma_parse_opts_t option bits */ +{ +#if JERRY_PARSER + JERRY_ASSERT (source_p != NULL); + + uint32_t is_strict_call = ECMA_PARSE_STRICT_MODE | ECMA_PARSE_DIRECT_EVAL; + + if ((parse_opts & is_strict_call) != is_strict_call) + { + parse_opts &= (uint32_t) ~ECMA_PARSE_STRICT_MODE; + } + + parse_opts |= ECMA_PARSE_EVAL; + + ECMA_CLEAR_LOCAL_PARSE_OPTS (); + + ecma_compiled_code_t *bytecode_p = parser_parse_script (source_p, parse_opts, NULL); + + if (JERRY_UNLIKELY (bytecode_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return vm_run_eval (bytecode_p, parse_opts); +#endif /* JERRY_PARSER */ +} /* ecma_op_eval_chars_buffer */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.h new file mode 100644 index 00000000..c06ad5d5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-eval.h @@ -0,0 +1,37 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_EVAL_H +#define ECMA_EVAL_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup eval eval + * @{ + */ + +ecma_value_t ecma_op_eval (ecma_value_t source_code, uint32_t parse_opts); + +ecma_value_t ecma_op_eval_chars_buffer (void *source_p, uint32_t parse_opts); + +/** + * @} + * @} + */ + +#endif /* !ECMA_EVAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.cpp new file mode 100644 index 00000000..675aaf92 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.cpp @@ -0,0 +1,520 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-exceptions.h" + +#include + +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-symbol-object.h" + +#include "jcontext.h" +#include "jrt.h" + +#if JERRY_LINE_INFO +#include "vm.h" +#endif /* JERRY_LINE_INFO */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup exceptions Exceptions + * @{ + */ + +/** + * Standard ecma-error object constructor. + * + * Note: + * message_string_p can be NULL. + * + * Note: + * calling with JERRY_ERROR_NONE does not make sense thus it will + * cause a fault in the system. + * + * @return pointer to ecma-object representing specified error + * with reference counter set to one. + */ +ecma_object_t * +ecma_new_standard_error (jerry_error_t error_type, /**< native error type */ + ecma_string_t *message_string_p) /**< message string */ +{ +#if JERRY_BUILTIN_ERRORS + ecma_builtin_id_t prototype_id = ECMA_BUILTIN_ID__COUNT; + + switch (error_type) + { + case JERRY_ERROR_EVAL: + { + prototype_id = ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_RANGE: + { + prototype_id = ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_REFERENCE: + { + prototype_id = ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_TYPE: + { + prototype_id = ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_AGGREGATE: + { + prototype_id = ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_URI: + { + prototype_id = ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE; + break; + } + + case JERRY_ERROR_SYNTAX: + { + prototype_id = ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE; + break; + } + + default: + { + JERRY_ASSERT (error_type == JERRY_ERROR_COMMON); + + prototype_id = ECMA_BUILTIN_ID_ERROR_PROTOTYPE; + break; + } + } +#else /* !JERRY_BUILTIN_ERRORS */ + JERRY_UNUSED (error_type); + ecma_builtin_id_t prototype_id = ECMA_BUILTIN_ID_ERROR_PROTOTYPE; +#endif /* JERRY_BUILTIN_ERRORS */ + + ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id); + + ecma_object_t *error_object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) error_object_p; + extended_object_p->u.cls.type = ECMA_OBJECT_CLASS_ERROR; + extended_object_p->u.cls.u1.error_type = (uint8_t) error_type; + + if (message_string_p != NULL) + { + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (error_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + + ecma_ref_ecma_string (message_string_p); + prop_value_p->value = ecma_make_string_value (message_string_p); + } + + /* Avoid calling the decorator function recursively. */ + if (JERRY_CONTEXT (error_object_created_callback_p) != NULL + && !(JERRY_CONTEXT (status_flags) & ECMA_STATUS_ERROR_UPDATE)) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_UPDATE; + JERRY_CONTEXT (error_object_created_callback_p) + (ecma_make_object_value (error_object_p), JERRY_CONTEXT (error_object_created_callback_user_p)); + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_ERROR_UPDATE; + } + else + { +#if JERRY_LINE_INFO + /* Default decorator when line info is enabled. */ + ecma_string_t *stack_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_STACK); + + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (error_object_p, stack_str_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, NULL); + ecma_deref_ecma_string (stack_str_p); + + ecma_value_t backtrace_value = vm_get_backtrace (0); + + prop_value_p->value = backtrace_value; + ecma_deref_object (ecma_get_object_from_value (backtrace_value)); +#endif /* JERRY_LINE_INFO */ + } + + return error_object_p; +} /* ecma_new_standard_error */ + +/** + * aggregate-error object constructor. + * + * @return newly constructed aggregate errors + */ +ecma_value_t +ecma_new_aggregate_error (ecma_value_t error_list_val, /**< errors list */ + ecma_value_t message_val) /**< message string */ +{ + ecma_object_t *new_error_object_p; + + if (!ecma_is_value_undefined (message_val)) + { + ecma_string_t *message_string_p = ecma_op_to_string (message_val); + + if (JERRY_UNLIKELY (message_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + new_error_object_p = ecma_new_standard_error (JERRY_ERROR_AGGREGATE, message_string_p); + ecma_deref_ecma_string (message_string_p); + } + else + { + new_error_object_p = ecma_new_standard_error (JERRY_ERROR_AGGREGATE, NULL); + } + + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (error_list_val, LIT_GLOBAL_SYMBOL_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + ecma_deref_object (new_error_object_p); + return using_iterator; + } + + if (!ecma_is_value_undefined (using_iterator)) + { + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (error_list_val, using_iterator, &next_method); + ecma_free_value (using_iterator); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + ecma_deref_object (new_error_object_p); + return iterator; + } + + ecma_collection_t *error_list_p = ecma_new_collection (); + ecma_value_t result = ECMA_VALUE_ERROR; + + while (true) + { + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next)) + { + break; + } + + if (next == ECMA_VALUE_FALSE) + { + result = ECMA_VALUE_UNDEFINED; + break; + } + + /* 8.e.iii */ + ecma_value_t next_error = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (next_error)) + { + break; + } + + ecma_collection_push_back (error_list_p, next_error); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_collection_free (error_list_p); + ecma_deref_object (new_error_object_p); + return result; + } + + JERRY_ASSERT (ecma_is_value_undefined (result)); + + ecma_value_t error_list_arr = ecma_op_new_array_object_from_collection (error_list_p, true); + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (new_error_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_ERRORS_UL), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + prop_value_p->value = error_list_arr; + ecma_free_value (error_list_arr); + } + + return ecma_make_object_value (new_error_object_p); +} /* ecma_new_aggregate_error */ + +/** + * Return the error type for an Error object. + * + * @return one of the jerry_error_t value + * if it is not an Error object then JERRY_ERROR_NONE will be returned + */ +jerry_error_t +ecma_get_error_type (ecma_object_t *error_object_p) /**< possible error object */ +{ + if (!ecma_object_class_is (error_object_p, ECMA_OBJECT_CLASS_ERROR)) + { + return JERRY_ERROR_NONE; + } + + return (jerry_error_t) ((ecma_extended_object_t *) error_object_p)->u.cls.u1.error_type; +} /* ecma_get_error_type */ + +/** + * Raise a standard ecma-error with the given type and message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_standard_error (jerry_error_t error_type, /**< error type */ + ecma_error_msg_t msg) /**< error message */ +{ + ecma_object_t *error_obj_p; + const lit_utf8_byte_t *str_p = (lit_utf8_byte_t *) ecma_get_error_msg (msg); + + if (msg != ECMA_ERR_EMPTY) + { + ecma_string_t *error_msg_p = ecma_new_ecma_external_string_from_cesu8 (str_p, ecma_get_error_size (msg), NULL); + error_obj_p = ecma_new_standard_error (error_type, error_msg_p); + ecma_deref_ecma_string (error_msg_p); + } + else + { + error_obj_p = ecma_new_standard_error (error_type, NULL); + } + + jcontext_raise_exception (ecma_make_object_value (error_obj_p)); + return ECMA_VALUE_ERROR; +} /* ecma_raise_standard_error */ + +#if JERRY_ERROR_MESSAGES + +/** + * Raise a standard ecma-error with the given format string and arguments. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_standard_error_with_format (jerry_error_t error_type, /**< error type */ + const char *format, /**< format string */ + ...) /**< ecma-values */ +{ + JERRY_ASSERT (format != NULL); + + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + const char *start_p = format; + const char *end_p = format; + + va_list args; + + va_start (args, format); + + while (*end_p) + { + if (*end_p == '%') + { + /* Concat template string. */ + if (end_p > start_p) + { + ecma_stringbuilder_append_raw (&builder, (lit_utf8_byte_t *) start_p, (lit_utf8_size_t) (end_p - start_p)); + } + + /* Convert an argument to string without side effects. */ + ecma_string_t *arg_string_p; + const ecma_value_t arg_val = va_arg (args, ecma_value_t); + + if (JERRY_UNLIKELY (ecma_is_value_object (arg_val))) + { + ecma_object_t *arg_object_p = ecma_get_object_from_value (arg_val); + lit_magic_string_id_t class_name = ecma_object_get_class_name (arg_object_p); + arg_string_p = ecma_get_magic_string (class_name); + } + else if (ecma_is_value_symbol (arg_val)) + { + ecma_value_t symbol_desc_value = ecma_get_symbol_descriptive_string (arg_val); + arg_string_p = ecma_get_string_from_value (symbol_desc_value); + } + else + { + arg_string_p = ecma_op_to_string (arg_val); + JERRY_ASSERT (arg_string_p != NULL); + } + + /* Concat argument. */ + ecma_stringbuilder_append (&builder, arg_string_p); + + ecma_deref_ecma_string (arg_string_p); + + start_p = end_p + 1; + } + + end_p++; + } + + va_end (args); + + /* Concat reset of template string. */ + if (start_p < end_p) + { + ecma_stringbuilder_append_raw (&builder, (lit_utf8_byte_t *) start_p, (lit_utf8_size_t) (end_p - start_p)); + } + + ecma_string_t *builder_str_p = ecma_stringbuilder_finalize (&builder); + + ecma_object_t *error_obj_p = ecma_new_standard_error (error_type, builder_str_p); + + ecma_deref_ecma_string (builder_str_p); + + jcontext_raise_exception (ecma_make_object_value (error_obj_p)); + return ECMA_VALUE_ERROR; +} /* ecma_raise_standard_error_with_format */ + +#endif /* JERRY_ERROR_MESSAGES */ + +/** + * Raise a common error with the given message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_common_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_COMMON, msg); +} /* ecma_raise_common_error */ + +/** + * Raise a RangeError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_range_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_RANGE, msg); +} /* ecma_raise_range_error */ + +/** + * Raise a ReferenceError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_reference_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_REFERENCE, msg); +} /* ecma_raise_reference_error */ + +/** + * Raise a SyntaxError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_syntax_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_SYNTAX, msg); +} /* ecma_raise_syntax_error */ + +/** + * Raise a TypeError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_type_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_TYPE, msg); +} /* ecma_raise_type_error */ + +/** + * Raise a URIError with the given message. + * + * See also: ECMA-262 v5, 15.11.6.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_uri_error (ecma_error_msg_t msg) /**< error message */ +{ + return ecma_raise_standard_error (JERRY_ERROR_URI, msg); +} /* ecma_raise_uri_error */ + +#if (JERRY_STACK_LIMIT != 0) +/** + * Raise a RangeError with "Maximum call stack size exceeded" message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_maximum_callstack_error (void) +{ + return ecma_raise_range_error (ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED); +} /* ecma_raise_maximum_callstack_error */ +#endif /* (JERRY_STACK_LIMIT != 0) */ + +/** + * Raise a AggregateError with the given errors and message. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_raise_aggregate_error (ecma_value_t error_list_val, /**< errors list */ + ecma_value_t message_val) /**< error message */ +{ + ecma_value_t aggre_val = ecma_new_aggregate_error (error_list_val, message_val); + jcontext_raise_exception (aggre_val); + + return ECMA_VALUE_ERROR; +} /* ecma_raise_aggregate_error */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.h new file mode 100644 index 00000000..c367a6bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-exceptions.h @@ -0,0 +1,53 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_EXCEPTIONS_H +#define ECMA_EXCEPTIONS_H + +#include "ecma-globals.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup exceptions Exceptions + * @{ + */ + +jerry_error_t ecma_get_error_type (ecma_object_t *error_object_p); +ecma_object_t *ecma_new_standard_error (jerry_error_t error_type, ecma_string_t *message_string_p); +#if JERRY_ERROR_MESSAGES +ecma_value_t ecma_raise_standard_error_with_format (jerry_error_t error_type, const char *msg_p, ...); +#endif /* JERRY_ERROR_MESSAGES */ +ecma_value_t ecma_raise_standard_error (jerry_error_t error_type, ecma_error_msg_t msg); +ecma_value_t ecma_raise_common_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_range_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_reference_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_syntax_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_type_error (ecma_error_msg_t msg); +ecma_value_t ecma_raise_uri_error (ecma_error_msg_t msg); +#if (JERRY_STACK_LIMIT != 0) +ecma_value_t ecma_raise_maximum_callstack_error (void); +#endif /* (JERRY_STACK_LIMIT != 0) */ +ecma_value_t ecma_new_aggregate_error (ecma_value_t error_list_val, ecma_value_t message_val); +ecma_value_t ecma_raise_aggregate_error (ecma_value_t error_list_val, ecma_value_t message_val); + +/** + * @} + * @} + */ + +#endif /* !ECMA_EXCEPTIONS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.cpp new file mode 100644 index 00000000..2dde89e6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.cpp @@ -0,0 +1,2208 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-function-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtin-helpers.h" +#include "ecma-errors.h" +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" +#include "ecma-symbol-object.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" +#include "opcodes.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmafunctionobject ECMA Function object related routines + * @{ + */ + +/** + * SetFunctionName operation + * + * See also: ECMAScript v6, 9.2.1.1 + * + * @return source name as ecma-string + */ +ecma_value_t +ecma_op_function_form_name (ecma_string_t *prop_name_p, /**< property name */ + char *prefix_p, /**< prefix */ + lit_utf8_size_t prefix_size) /**< prefix length */ +{ + /* 4. */ + if (ecma_prop_name_is_symbol (prop_name_p)) + { + /* .a */ + ecma_value_t string_desc = ecma_get_symbol_description (prop_name_p); + + /* .b */ + if (ecma_is_value_undefined (string_desc)) + { + prop_name_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + /* .c */ + else + { + ecma_string_t *string_desc_p = ecma_get_string_from_value (string_desc); + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) "[", 1); + ecma_stringbuilder_append (&builder, string_desc_p); + ecma_stringbuilder_append_byte (&builder, (lit_utf8_byte_t) LIT_CHAR_RIGHT_SQUARE); + prop_name_p = ecma_stringbuilder_finalize (&builder); + } + } + else + { + ecma_ref_ecma_string (prop_name_p); + } + + /* 5. */ + if (JERRY_UNLIKELY (prefix_p != NULL)) + { + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) prefix_p, prefix_size); + ecma_stringbuilder_append (&builder, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + prop_name_p = ecma_stringbuilder_finalize (&builder); + } + + return ecma_make_string_value (prop_name_p); +} /* ecma_op_function_form_name */ + +#if JERRY_BUILTIN_PROXY +/** + * IsCallable operation for proxy object. + * + * @return true - if the given proxy object is callable; + * false - otherwise + */ +bool +ecma_op_proxy_object_is_callable (ecma_object_t *obj_p) /**< ecma object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + + return (obj_p->u2.prototype_cp & ECMA_PROXY_IS_CALLABLE) != 0; +} /* ecma_op_proxy_object_is_callable */ +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * IsCallable operation. + * + * See also: ECMA-262 v5, 9.11 + * + * @return true - if the given object is callable; + * false - otherwise + */ +bool +ecma_op_object_is_callable (ecma_object_t *obj_p) /**< ecma object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + const ecma_object_type_t type = ecma_get_object_type (obj_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_TYPE_IS_PROXY (type)) + { + return ecma_op_proxy_object_is_callable (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return type >= ECMA_OBJECT_TYPE_FUNCTION; +} /* ecma_op_object_is_callable */ + +/** + * IsCallable operation. + * + * See also: ECMA-262 v5, 9.11 + * + * @return true - if value is callable object; + * false - otherwise + */ +bool +ecma_op_is_callable (ecma_value_t value) /**< ecma value */ +{ + return (ecma_is_value_object (value) && ecma_op_object_is_callable (ecma_get_object_from_value (value))); +} /* ecma_op_is_callable */ + +/** + * Implement IsConstructor abstract operation. + * + * + * @return ECMA_IS_VALID_CONSTRUCTOR - if object is a valid for constructor call + * ecma_error_msg_t id of error - otherwise + */ +ecma_error_msg_t +ecma_object_check_constructor (ecma_object_t *obj_p) /**< ecma object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + ecma_object_type_t type = ecma_get_object_type (obj_p); + + if (JERRY_UNLIKELY (type < ECMA_OBJECT_TYPE_PROXY)) + { + return ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL; + } + + while (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)) + { + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) obj_p; + + obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + type = ecma_get_object_type (obj_p); + } + + if (JERRY_LIKELY (type == ECMA_OBJECT_TYPE_FUNCTION)) + { + const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) obj_p); + + if (!CBC_FUNCTION_IS_CONSTRUCTABLE (byte_code_p->status_flags)) + { +#if JERRY_ERROR_MESSAGES + switch (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags)) + { + case CBC_FUNCTION_SCRIPT: + { + return ECMA_ERR_SCRIPT_GLOBAL_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_GENERATOR: + { + return ECMA_ERR_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ASYNC: + { + return ECMA_ERR_ASYNC_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + return ECMA_ERR_ASYNC_GENERATOR_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ACCESSOR: + { + return ECMA_ERR_ACCESSOR_FUNCTIONS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_METHOD: + { + return ECMA_ERR_METHODS_INVOKE_WITH_NEW; + } + case CBC_FUNCTION_ARROW: + { + return ECMA_ERR_ARROW_FUNCTIONS_INVOKE_WITH_NEW; + } + default: + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_ASYNC_ARROW); + return ECMA_ERR_ASYNC_ARROW_FUNCTIONS_INVOKE_WITH_NEW; + } + } +#else /* !JERRY_ERROR_MESSAGES */ + return ECMA_ERR_EMPTY; +#endif /* JERRY_ERROR_MESSAGES */ + } + + return ECMA_IS_VALID_CONSTRUCTOR; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_TYPE_IS_PROXY (type)) + { + if (!(obj_p->u2.prototype_cp & ECMA_PROXY_IS_CONSTRUCTABLE)) + { + return ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR; + } + + return ECMA_IS_VALID_CONSTRUCTOR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION || type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + + if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) + { + if (ecma_builtin_function_is_routine (obj_p)) + { + return ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR; + } + + JERRY_ASSERT (((ecma_extended_object_t *) obj_p)->u.built_in.id != ECMA_BUILTIN_ID_HANDLER); + } + + return ECMA_IS_VALID_CONSTRUCTOR; +} /* ecma_object_check_constructor */ + +/** + * Implement IsConstructor abstract operation. + * + * @return ECMA_IS_VALID_CONSTRUCTOR - if the input value is a constructor. + * ecma_error_msg_t id of error - otherwise + */ +ecma_error_msg_t +ecma_check_constructor (ecma_value_t value) /**< ecma object */ +{ + if (!ecma_is_value_object (value)) + { + return ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL; + } + + return ecma_object_check_constructor (ecma_get_object_from_value (value)); +} /* ecma_check_constructor */ + +/** + * Checks whether the given object implements [[Construct]]. + * + * @return true - if the given object is constructor; + * false - otherwise + */ +bool +ecma_object_is_constructor (ecma_object_t *obj_p) /**< ecma object */ +{ + return ecma_object_check_constructor (obj_p) == ECMA_IS_VALID_CONSTRUCTOR; +} /* ecma_object_is_constructor */ + +/** + * Checks whether the value is Object that implements [[Construct]]. + * + * @return true - if value is constructor object; + * false - otherwise + */ +bool +ecma_is_constructor (ecma_value_t value) /**< ecma value */ +{ + return (ecma_is_value_object (value) && ecma_object_is_constructor (ecma_get_object_from_value (value))); +} /* ecma_is_constructor */ + +/** + * Helper method to count and convert the arguments for the Function/GeneratorFunction constructor call. + * + * See also: + * ECMA 262 v5.1 15.3.2.1 steps 5.a-d + * ECMA 262 v6 19.2.1.1.1 steps 8 + * + * @return ecma value - concatenated arguments as a string. + * Returned value must be freed with ecma_free_value. + */ +static ecma_string_t * +ecma_op_create_dynamic_function_arguments_helper (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len <= 1) + { + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return str_p; + } + + if (arguments_list_len == 2) + { + return str_p; + } + + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (str_p); + ecma_deref_ecma_string (str_p); + + for (uint32_t idx = 1; idx < arguments_list_len - 1; idx++) + { + str_p = ecma_op_to_string (arguments_list_p[idx]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + ecma_stringbuilder_destroy (&builder); + return str_p; + } + + ecma_stringbuilder_append_char (&builder, LIT_CHAR_COMMA); + ecma_stringbuilder_append (&builder, str_p); + ecma_deref_ecma_string (str_p); + } + + return ecma_stringbuilder_finalize (&builder); +} /* ecma_op_create_dynamic_function_arguments_helper */ + +/** + * Function object creation operation. + * + * See also: ECMA-262 v5, 13.2 + * + * @return pointer to newly created Function object + */ +static ecma_object_t * +ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p, /**< byte-code array */ + ecma_builtin_id_t proto_id) /**< builtin id of the prototype object */ +{ + JERRY_ASSERT (ecma_is_lexical_environment (scope_p)); + + /* 1., 4., 13. */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + size_t function_object_size = sizeof (ecma_extended_object_t); + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + function_object_size = sizeof (ecma_static_function_t); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_object_t *func_p = ecma_create_object (prototype_obj_p, function_object_size, ECMA_OBJECT_TYPE_FUNCTION); + + /* 2., 6., 7., 8. */ + /* + * We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object. + * Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION + * that defines which version of the routine should be used on demand. + */ + + /* 3. */ + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; + + /* 9. */ + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, scope_p, 0); + + /* 10., 11., 12. */ + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + ext_func_p->u.function.bytecode_cp = JMEM_CP_NULL; + ((ecma_static_function_t *) func_p)->bytecode_p = bytecode_data_p; + } + else +#endif /* JERRY_SNAPSHOT_EXEC */ + { + ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p); + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); + } + + /* 14., 15., 16., 17., 18. */ + /* + * 'length' and 'prototype' properties are instantiated lazily + * + * See also: ecma_op_function_try_to_lazy_instantiate_property + */ + + return func_p; +} /* ecma_op_create_function_object */ + +/** + * CreateDynamicFunction operation + * + * See also: + * ECMA-262 v5, 15.3. + * ECMA-262 v6, 19.2.1.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * constructed function object - otherwise + */ +ecma_value_t +ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len, /**< number of arguments */ + ecma_parse_opts_t parse_opts) /**< parse options */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_string_t *arguments_str_p = + ecma_op_create_dynamic_function_arguments_helper (arguments_list_p, arguments_list_len); + + if (JERRY_UNLIKELY (arguments_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *function_body_str_p; + + if (arguments_list_len > 0) + { + function_body_str_p = ecma_op_to_string (arguments_list_p[arguments_list_len - 1]); + + if (JERRY_UNLIKELY (function_body_str_p == NULL)) + { + ecma_deref_ecma_string (arguments_str_p); + return ECMA_VALUE_ERROR; + } + } + else + { + /* Very unlikely code path, not optimized. */ + function_body_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t source[2]; + source[0] = ecma_make_string_value (function_body_str_p); + source[1] = ecma_make_string_value (arguments_str_p); + + parse_opts = (ecma_parse_opts_t) ((int) parse_opts | ((int) ECMA_PARSE_HAS_SOURCE_VALUE | (int) ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE)); + + ecma_compiled_code_t *bytecode_p = parser_parse_script ((void *) source, parse_opts, NULL); + + ecma_deref_ecma_string (arguments_str_p); + ecma_deref_ecma_string (function_body_str_p); + + if (JERRY_UNLIKELY (bytecode_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t *func_name_p; + func_name_p = ecma_compiled_code_resolve_function_name ((const ecma_compiled_code_t *) bytecode_p); + *func_name_p = ecma_make_magic_string_value (LIT_MAGIC_STRING_ANONYMOUS); + + ecma_object_t *global_object_p = ecma_builtin_get_global (); + +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (global_object_p == (ecma_object_t *) ecma_op_function_get_realm (bytecode_p)); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *global_env_p = ecma_get_global_environment (global_object_p); + ecma_builtin_id_t fallback_proto = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE; + ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target_p); + ecma_builtin_id_t fallback_ctor = ECMA_BUILTIN_ID_FUNCTION; + + if (JERRY_UNLIKELY (parse_opts & (ECMA_PARSE_GENERATOR_FUNCTION | ECMA_PARSE_ASYNC_FUNCTION))) + { + fallback_proto = ECMA_BUILTIN_ID_ASYNC_GENERATOR; + fallback_ctor = ECMA_BUILTIN_ID_ASYNC_GENERATOR_FUNCTION; + + if (!(parse_opts & ECMA_PARSE_GENERATOR_FUNCTION)) + { + fallback_proto = ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE; + fallback_ctor = ECMA_BUILTIN_ID_ASYNC_FUNCTION; + } + else if (!(parse_opts & ECMA_PARSE_ASYNC_FUNCTION)) + { + fallback_proto = ECMA_BUILTIN_ID_GENERATOR; + fallback_ctor = ECMA_BUILTIN_ID_GENERATOR_FUNCTION; + } + } + + if (new_target_p == NULL) + { + new_target_p = ecma_builtin_get (fallback_ctor); + } + + ecma_object_t *proto = ecma_op_get_prototype_from_constructor (new_target_p, fallback_proto); + + if (JERRY_UNLIKELY (proto == NULL)) + { + ecma_bytecode_deref (bytecode_p); + return ECMA_VALUE_ERROR; + } + + ecma_object_t *func_obj_p = ecma_op_create_function_object (global_env_p, bytecode_p, fallback_proto); + + ECMA_SET_NON_NULL_POINTER (func_obj_p->u2.prototype_cp, proto); + ecma_deref_object (proto); + + ecma_bytecode_deref (bytecode_p); + return ecma_make_object_value (func_obj_p); +} /* ecma_op_create_dynamic_function */ + +/** + * Function object creation operation. + * + * See also: ECMA-262 v5, 13.2 + * + * @return pointer to newly created Function object + */ +ecma_object_t * +ecma_op_create_simple_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */ +{ + return ecma_op_create_function_object (scope_p, bytecode_data_p, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); +} /* ecma_op_create_simple_function_object */ + +/** + * Create a function object with the appropriate prototype. + * + * @return pointer to newly created Function object + */ +ecma_object_t * +ecma_op_create_any_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */ +{ + ecma_builtin_id_t proto_id; + + switch (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags)) + { + case CBC_FUNCTION_GENERATOR: + { + proto_id = ECMA_BUILTIN_ID_GENERATOR; + break; + } + case CBC_FUNCTION_ASYNC: + { + proto_id = ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE; + break; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + proto_id = ECMA_BUILTIN_ID_ASYNC_GENERATOR; + break; + } + default: + { + proto_id = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE; + break; + } + } + + return ecma_op_create_function_object (scope_p, bytecode_data_p, proto_id); +} /* ecma_op_create_any_function_object */ + +/** + * Arrow function object creation operation. + * + * See also: ES2015, 9.2.12 + * + * @return pointer to newly created Function object + */ +ecma_object_t * +ecma_op_create_arrow_function_object (ecma_object_t *scope_p, /**< function's scope */ + const ecma_compiled_code_t *bytecode_data_p, /**< byte-code array */ + ecma_value_t this_binding) /**< value of 'this' binding */ +{ + ecma_object_t *prototype_obj_p; + + if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_ARROW) + { + prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + } + else + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_ASYNC_ARROW); + prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE); + } + + size_t arrow_function_object_size = sizeof (ecma_arrow_function_t); + +#if JERRY_SNAPSHOT_EXEC + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + arrow_function_object_size = sizeof (ecma_static_arrow_function_t); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_object_t *func_p = ecma_create_object (prototype_obj_p, arrow_function_object_size, ECMA_OBJECT_TYPE_FUNCTION); + + ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_p; + + ECMA_SET_NON_NULL_POINTER_TAG (arrow_func_p->header.u.function.scope_cp, scope_p, 0); + +#if JERRY_SNAPSHOT_EXEC + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + arrow_func_p->header.u.function.bytecode_cp = ECMA_NULL_POINTER; + ((ecma_static_arrow_function_t *) func_p)->bytecode_p = bytecode_data_p; + } + else + { +#endif /* JERRY_SNAPSHOT_EXEC */ + ECMA_SET_INTERNAL_VALUE_POINTER (arrow_func_p->header.u.function.bytecode_cp, bytecode_data_p); + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); +#if JERRY_SNAPSHOT_EXEC + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + arrow_func_p->this_binding = ecma_copy_value_if_not_object (this_binding); + arrow_func_p->new_target = ECMA_VALUE_UNDEFINED; + + if (JERRY_CONTEXT (current_new_target_p) != NULL) + { + arrow_func_p->new_target = ecma_make_object_value (JERRY_CONTEXT (current_new_target_p)); + } + return func_p; +} /* ecma_op_create_arrow_function_object */ + +/** + * External function object creation operation. + * + * Note: + * external function object is implementation-defined object type + * that represent functions implemented in native code, using Embedding API + * + * @return pointer to newly created external function object + */ +ecma_object_t * +ecma_op_create_external_function_object (ecma_native_handler_t handler_cb) /**< pointer to external native handler */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + + ecma_object_t *function_obj_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_native_function_t), ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + /* + * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_NATIVE_FUNCTION type. + * + * See also: ecma_object_get_class_name + */ + + ecma_native_function_t *native_function_p = (ecma_native_function_t *) function_obj_p; +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (native_function_p->realm_value, ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + native_function_p->native_handler_cb = handler_cb; + + return function_obj_p; +} /* ecma_op_create_external_function_object */ + +/** + * Create built-in native handler object. + * + * @return pointer to newly created native handler object + */ +ecma_object_t * +ecma_op_create_native_handler (ecma_native_handler_id_t id, /**< handler id */ + size_t object_size) /**< created object size */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + + ecma_object_t *function_obj_p = ecma_create_object (prototype_obj_p, object_size, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p; + ext_func_obj_p->u.built_in.id = ECMA_BUILTIN_ID_HANDLER; + ext_func_obj_p->u.built_in.routine_id = (uint8_t) id; + ext_func_obj_p->u.built_in.u2.routine_flags = ECMA_NATIVE_HANDLER_FLAGS_NONE; + +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_obj_p->u.built_in.realm_value, ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + + return function_obj_p; +} /* ecma_op_create_native_handler */ + +/** + * Get compiled code of a function object. + * + * @return compiled code + */ +const ecma_compiled_code_t * +ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p) /**< function pointer */ +{ +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (function_p->u.function.bytecode_cp != ECMA_NULL_POINTER)) + { + return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, function_p->u.function.bytecode_cp); + } + + return ((ecma_static_function_t *) function_p)->bytecode_p; +#else /* !JERRY_SNAPSHOT_EXEC */ + return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, function_p->u.function.bytecode_cp); +#endif /* JERRY_SNAPSHOT_EXEC */ +} /* ecma_op_function_get_compiled_code */ + +#if JERRY_BUILTIN_REALMS + +/** + * Get realm from a byte code. + * + * Note: + * Does not increase the reference counter. + * + * @return pointer to realm (global) object + */ +ecma_global_object_t * +ecma_op_function_get_realm (const ecma_compiled_code_t *bytecode_header_p) /**< byte code header */ +{ +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + return (ecma_global_object_t *) ecma_builtin_get_global (); + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return (ecma_global_object_t *) script_p->realm_p; +} /* ecma_op_function_get_realm */ + +/** + * Get realm from a function + * + * Note: + * Does not increase the reference counter. + * + * @return realm (global) object + */ +ecma_global_object_t * +ecma_op_function_get_function_realm (ecma_object_t *func_obj_p) /**< function object */ +{ + while (true) + { + ecma_object_type_t type = ecma_get_object_type (func_obj_p); + + if (type == ECMA_OBJECT_TYPE_FUNCTION) + { + ecma_extended_object_t *ext_function_obj_p = (ecma_extended_object_t *) func_obj_p; + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_function_obj_p); + return ecma_op_function_get_realm (bytecode_data_p); + } + + if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) + { + ecma_extended_object_t *ext_function_obj_p = (ecma_extended_object_t *) func_obj_p; + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, ext_function_obj_p->u.built_in.realm_value); + } + + if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION) + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); + } + + if (type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION) + { + ecma_value_t script_value = ((ecma_extended_object_t *) func_obj_p)->u.constructor_function.script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return (ecma_global_object_t *) script_p->realm_p; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (func_obj_p)) + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) func_obj_p; + if (ecma_is_value_null (proxy_obj_p->handler)) + { + ecma_raise_type_error (ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID); + return NULL; + } + func_obj_p = ecma_get_object_from_value (proxy_obj_p->target); + continue; + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; + func_obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + } +} /* ecma_op_function_get_function_realm */ + +#endif /* JERRY_BUILTIN_REALMS */ + +/** + * 15.3.5.3 implementation of [[HasInstance]] for Function objects + * + * @return true/false - if arguments are valid + * error - otherwise + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t value) /**< argument 'V' */ +{ + JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); + + if (!ecma_is_value_object (value)) + { + return ECMA_VALUE_FALSE; + } + + while (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION) + { + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + /* 1. 3. */ + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; + + func_obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + } + + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION + || ECMA_OBJECT_IS_PROXY (func_obj_p)); + + ecma_object_t *v_obj_p = ecma_get_object_from_value (value); + + ecma_value_t prototype_obj_value = ecma_op_object_get_by_magic_id (func_obj_p, LIT_MAGIC_STRING_PROTOTYPE); + + if (ECMA_IS_VALUE_ERROR (prototype_obj_value)) + { + return prototype_obj_value; + } + + if (!ecma_is_value_object (prototype_obj_value)) + { + ecma_free_value (prototype_obj_value); + return ecma_raise_type_error (ECMA_ERR_OBJECT_EXPECTED); + } + + ecma_object_t *prototype_obj_p = ecma_get_object_from_value (prototype_obj_value); + JERRY_ASSERT (prototype_obj_p != NULL); + +#if JERRY_BUILTIN_PROXY + ecma_value_t result = ECMA_VALUE_ERROR; +#else /* !JERRY_BUILTIN_PROXY */ + ecma_value_t result = ECMA_VALUE_FALSE; +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_ref_object (v_obj_p); + + while (true) + { + ecma_object_t *current_proto_p = ecma_op_object_get_prototype_of (v_obj_p); + ecma_deref_object (v_obj_p); + + if (current_proto_p == NULL) + { +#if JERRY_BUILTIN_PROXY + result = ECMA_VALUE_FALSE; +#endif /* JERRY_BUILTIN_PROXY */ + break; + } + else if (current_proto_p == ECMA_OBJECT_POINTER_ERROR) + { + break; + } + + if (current_proto_p == prototype_obj_p) + { + ecma_deref_object (current_proto_p); + result = ECMA_VALUE_TRUE; + break; + } + + /* Advance up on prototype chain. */ + v_obj_p = current_proto_p; + } + + ecma_deref_object (prototype_obj_p); + return result; +} /* ecma_op_function_has_instance */ + +/** + * GetSuperConstructor operation for class methods + * + * See also: ECMAScript v6, 12.3.5.2 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * super constructor - otherwise + */ +ecma_value_t +ecma_op_function_get_super_constructor (ecma_object_t *func_obj_p) /**< function object */ +{ + ecma_object_t *super_ctor_p = ecma_op_object_get_prototype_of (func_obj_p); + + if (JERRY_UNLIKELY (super_ctor_p == ECMA_OBJECT_POINTER_ERROR)) + { + return ECMA_VALUE_ERROR; + } + else if (super_ctor_p == NULL || !ecma_object_is_constructor (super_ctor_p)) + { + if (super_ctor_p != NULL) + { + ecma_deref_object (super_ctor_p); + } + return ecma_raise_type_error (ECMA_ERR_SUPER_BINDING_MUST_BE_A_CONSTRUCTOR); + } + + return ecma_make_object_value (super_ctor_p); +} /* ecma_op_function_get_super_constructor */ + +/** + * Ordinary internal method: GetPrototypeFromConstructor (constructor, intrinsicDefaultProto) + * + * See also: + * - ECMAScript v6, 9.1.15 + * - ECMAScript v10, 9.1.14 + * + * @return NULL - if the operation fail (exception on the global context is raised) + * pointer to the prototype object - otherwise + */ +ecma_object_t * +ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< constructor to get prototype from */ + ecma_builtin_id_t default_proto_id) /**< intrinsicDefaultProto */ +{ + JERRY_ASSERT (ecma_op_object_is_callable (ctor_obj_p)); + JERRY_ASSERT (default_proto_id < ECMA_BUILTIN_ID__COUNT); + + ecma_value_t proto = ecma_op_object_get_by_magic_id (ctor_obj_p, LIT_MAGIC_STRING_PROTOTYPE); + + if (ECMA_IS_VALUE_ERROR (proto)) + { + return NULL; + } + + ecma_object_t *proto_obj_p; + + if (!ecma_is_value_object (proto)) + { + ecma_free_value (proto); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (ctor_obj_p)) + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) ctor_obj_p; + if (ecma_is_value_null (proxy_obj_p->handler)) + { + ecma_raise_type_error (ECMA_ERR_PROTOTYPE_FROM_REVOKED_PROXY_IS_INVALID); + return NULL; + } + } +#endif /* JERRY_BUILTIN_PROXY */ + +#if JERRY_BUILTIN_REALMS + proto_obj_p = ecma_builtin_get_from_realm (ecma_op_function_get_function_realm (ctor_obj_p), default_proto_id); +#else /* !JERRY_BUILTIN_REALMS */ + proto_obj_p = ecma_builtin_get (default_proto_id); +#endif /* JERRY_BUILTIN_REALMS */ + ecma_ref_object (proto_obj_p); + } + else + { + proto_obj_p = ecma_get_object_from_value (proto); + } + + return proto_obj_p; +} /* ecma_op_get_prototype_from_constructor */ + +/** + * Perform a JavaScript class function object method call. + * + * The input function object should be a JavaScript class constructor + * + * @return the result of the function call. + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_constructor (vm_frame_ctx_shared_args_t *shared_args_p, /**< shared data */ + ecma_object_t *scope_p, /**< lexical environment to use */ + ecma_value_t this_binding) /**< value of 'ThisBinding' */ +{ + shared_args_p->header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; + + ecma_value_t ret_value; + ecma_global_object_t *saved_global_object_p; + ecma_extended_object_t *ext_func_p; + + if (JERRY_CONTEXT (current_new_target_p) == NULL) + { + ret_value = ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW); + goto exit; + } + + ext_func_p = (ecma_extended_object_t *) shared_args_p->header.function_object_p; + if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + this_binding = ECMA_VALUE_UNINITIALIZED; + } + + ecma_op_create_environment_record (scope_p, this_binding, shared_args_p->header.function_object_p); + +#if JERRY_BUILTIN_REALMS + saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = ecma_op_function_get_realm (shared_args_p->header.bytecode_header_p); +#endif /* JERRY_BUILTIN_REALMS */ + + ret_value = vm_run (&shared_args_p->header, this_binding, scope_p); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + /* ECMAScript v6, 9.2.2.13 */ + if (JERRY_UNLIKELY (this_binding == ECMA_VALUE_UNINITIALIZED)) + { + if (!ECMA_IS_VALUE_ERROR (ret_value) && !ecma_is_value_object (ret_value)) + { + if (!ecma_is_value_undefined (ret_value)) + { + ecma_free_value (ret_value); + ret_value = ecma_raise_type_error (ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED); + } + else + { + ret_value = ecma_op_get_this_binding (scope_p); + } + } + } + +exit: + if (JERRY_UNLIKELY (shared_args_p->header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV)) + { + ecma_deref_object (scope_p); + } + + return ret_value; +} /* ecma_op_function_call_constructor */ + +/** + * Perform a JavaScript function object method call. + * + * The input function object should be a pure JavaScript method + * + * @return the result of the function call. + */ +static ecma_value_t +ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_binding, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + + vm_frame_ctx_shared_args_t shared_args; + shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST; + shared_args.header.function_object_p = func_obj_p; + shared_args.arg_list_p = arguments_list_p; + shared_args.arg_list_len = arguments_list_len; + + /* Entering Function Code (ECMA-262 v5, 10.4.3) */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; + + ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp); + + /* 8. */ + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + uint16_t status_flags = bytecode_data_p->status_flags; + + shared_args.header.bytecode_header_p = bytecode_data_p; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *realm_p = ecma_op_function_get_realm (bytecode_data_p); +#endif /* JERRY_BUILTIN_REALMS */ + + /* 5. */ + if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) + { + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV; + scope_p = ecma_create_decl_lex_env (scope_p); + } + + /* 1. */ + switch (CBC_FUNCTION_GET_TYPE (status_flags)) + { + case CBC_FUNCTION_CONSTRUCTOR: + { + return ecma_op_function_call_constructor (&shared_args, scope_p, this_binding); + } + case CBC_FUNCTION_ARROW: + { + ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p; + + if (ecma_is_value_undefined (arrow_func_p->new_target)) + { + JERRY_CONTEXT (current_new_target_p) = NULL; + } + else + { + JERRY_CONTEXT (current_new_target_p) = ecma_get_object_from_value (arrow_func_p->new_target); + } + + this_binding = arrow_func_p->this_binding; + + if (JERRY_UNLIKELY (this_binding == ECMA_VALUE_UNINITIALIZED)) + { + ecma_environment_record_t *env_record_p = ecma_op_get_environment_record (scope_p); + JERRY_ASSERT (env_record_p); + this_binding = env_record_p->this_binding; + } + break; + } + default: + { + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; + + if (status_flags & CBC_CODE_FLAGS_STRICT_MODE) + { + break; + } + + if (ecma_is_value_undefined (this_binding) || ecma_is_value_null (this_binding)) + { + /* 2. */ +#if JERRY_BUILTIN_REALMS + this_binding = realm_p->this_binding; +#else /* !JERRY_BUILTIN_REALMS */ + this_binding = ecma_make_object_value (ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + } + else if (!ecma_is_value_object (this_binding)) + { + /* 3., 4. */ + this_binding = ecma_op_to_object (this_binding); + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_THIS; + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding)); + } + break; + } + } + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = realm_p; +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t ret_value = vm_run (&shared_args.header, this_binding, scope_p); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV)) + { + ecma_deref_object (scope_p); + } + + if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_THIS)) + { + ecma_free_value (this_binding); + } + + return ret_value; +} /* ecma_op_function_call_simple */ + +/** + * Perform a built-in method call. + * + * @return the result of the function call. + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_native_built_in (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + JERRY_CONTEXT (global_object_p) = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, ext_func_obj_p->u.built_in.realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t ret_value = + ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + return ret_value; +} /* ecma_op_function_call_native_built_in */ + +/** + * Perform a native C method call which was registered via the API. + * + * @return the result of the function call. + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_native (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + + jerry_call_info_t call_info; + call_info.function = ecma_make_object_value (func_obj_p); + call_info.this_value = this_arg_value; + + ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target_p); + call_info.new_target = (new_target_p == NULL) ? ECMA_VALUE_UNDEFINED : ecma_make_object_value (new_target_p); + + JERRY_ASSERT (native_function_p->native_handler_cb != NULL); + ecma_value_t ret_value = native_function_p->native_handler_cb (&call_info, arguments_list_p, arguments_list_len); +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + if (JERRY_UNLIKELY (ecma_is_value_exception (ret_value))) + { + ecma_throw_exception (ret_value); + return ECMA_VALUE_ERROR; + } + + return ret_value; +} /* ecma_op_function_call_native */ + +/** + * Append the bound arguments into the given collection + * + * Note: + * - The whole bound chain is resolved + * - The first element of the collection contains the bounded this value + * + * @return target function of the bound function + */ +JERRY_ATTR_NOINLINE static ecma_object_t * +ecma_op_bound_function_get_argument_list (ecma_object_t *func_obj_p, /**< bound bunction object */ + ecma_collection_t *list_p) /**< list of arguments */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; + + func_obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + + uint32_t args_length = 1; + + if (ecma_is_value_integer_number (args_len_or_this)) + { + args_length = (uint32_t) ecma_get_integer_from_value (args_len_or_this); + } + + /* 5. */ + if (args_length != 1) + { + const ecma_value_t *args_p = (const ecma_value_t *) (bound_func_p + 1); + list_p->buffer_p[0] = *args_p; + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION) + { + func_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, list_p); + } + ecma_collection_append (list_p, args_p + 1, args_length - 1); + } + else + { + list_p->buffer_p[0] = args_len_or_this; + } + + return func_obj_p; +} /* ecma_op_bound_function_get_argument_list */ + +/** + * [[Call]] internal method for bound function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_call_bound (ecma_object_t *func_obj_p, /**< Function object */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; + + ecma_collection_t *bound_arg_list_p = ecma_new_collection (); + ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); + + ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); + + ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); + + JERRY_ASSERT (!ecma_is_value_empty (bound_arg_list_p->buffer_p[0])); + + ecma_value_t ret_value = ecma_op_function_call (target_obj_p, + bound_arg_list_p->buffer_p[0], + bound_arg_list_p->buffer_p + 1, + (uint32_t) (bound_arg_list_p->item_count - 1)); + + ecma_collection_destroy (bound_arg_list_p); + + return ret_value; +} /* ecma_op_function_call_bound */ + +/** + * General [[Call]] implementation + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_validated_call (ecma_value_t callee, /**< callee */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + if (!ecma_is_value_object (callee)) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + } + + return ecma_op_function_call (ecma_get_object_from_value (callee), + this_arg_value, + arguments_list_p, + arguments_list_len); +} /* ecma_op_function_validated_call */ + +/** + * General [[Call]] implementation + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); + + ECMA_CHECK_STACK_USAGE (); + + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + + if (JERRY_UNLIKELY (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL))) + { + JERRY_CONTEXT (current_new_target_p) = NULL; + } + + ecma_value_t result; + + switch (ecma_get_object_type (func_obj_p)) + { + case ECMA_OBJECT_TYPE_FUNCTION: + { + result = ecma_op_function_call_simple (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + result = ecma_op_function_call_native_built_in (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + result = ecma_proxy_object_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + result = ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_NEW); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + result = ecma_op_function_call_native (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + result = ecma_op_function_call_bound (func_obj_p, arguments_list_p, arguments_list_len); + break; + } + default: + { + result = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + break; + } + } + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + + return result; +} /* ecma_op_function_call */ + +/** + * [[Construct]] internal method for ECMAScript function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_simple (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + + ecma_object_t *new_this_obj_p = NULL; + ecma_value_t this_arg; + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + + /* 5. */ + if (!ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_obj_p->u.function.scope_cp)) + { + /* 5.a */ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + /* 5.b */ + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + this_arg = ecma_make_object_value (new_this_obj_p); + } + else + { + this_arg = ECMA_VALUE_UNDEFINED; + } + + /* 6. */ + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + + ecma_value_t ret_value = ecma_op_function_call_simple (func_obj_p, this_arg, arguments_list_p, arguments_list_len); + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + + /* 13.a */ + if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) + { + if (new_this_obj_p != NULL) + { + ecma_deref_object (new_this_obj_p); + } + + return ret_value; + } + + /* 13.b */ + ecma_free_value (ret_value); + return this_arg; +} /* ecma_op_function_construct_simple */ + +/** + * [[Construct]] internal method for built-in function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_built_in (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_UNUSED (new_target_p); + + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + ecma_value_t realm_value = ((ecma_extended_object_t *) func_obj_p)->u.built_in.realm_value; + JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + + ecma_value_t ret_value = ecma_builtin_dispatch_construct (func_obj_p, arguments_list_p, arguments_list_len); + + JERRY_CONTEXT (current_new_target_p) = old_new_target; + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + return ret_value; +} /* ecma_op_function_construct_built_in */ + +/** + * [[Construct]] internal method for bound function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t JERRY_ATTR_NOINLINE +ecma_op_function_construct_bound (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + ecma_collection_t *bound_arg_list_p = ecma_new_collection (); + ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); + + ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); + + ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); + + if (func_obj_p == new_target_p) + { + new_target_p = target_obj_p; + } + + ecma_value_t ret_value = ecma_op_function_construct (target_obj_p, + new_target_p, + bound_arg_list_p->buffer_p + 1, + (uint32_t) (bound_arg_list_p->item_count - 1)); + + ecma_collection_destroy (bound_arg_list_p); + + return ret_value; +} /* ecma_op_function_construct_bound */ + +/** + * [[Construct]] internal method for class implicit constructor objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_constructor (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + + ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) func_obj_p; + + if (!(constructor_object_p->u.constructor_function.flags & ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE)) + { + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_object_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + + jerry_value_t new_this_value = ecma_make_object_value (new_this_object_p); + jerry_value_t ret_value = opfunc_init_class_fields (func_obj_p, new_this_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_this_object_p); + return ret_value; + } + + return new_this_value; + } + + ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p); + + if (ECMA_IS_VALUE_ERROR (super_ctor)) + { + return super_ctor; + } + + ecma_object_t *super_ctor_p = ecma_get_object_from_value (super_ctor); + ecma_value_t result = ecma_op_function_construct (super_ctor_p, new_target_p, arguments_list_p, arguments_list_len); + ecma_deref_object (super_ctor_p); + + if (ecma_is_value_object (result)) + { + ecma_value_t fields_value = opfunc_init_class_fields (func_obj_p, result); + + if (ECMA_IS_VALUE_ERROR (fields_value)) + { + ecma_free_value (result); + return fields_value; + } + } + + return result; +} /* ecma_op_function_construct_constructor */ + +/** + * [[Construct]] internal method for external function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_native (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_value_t this_arg = ecma_make_object_value (new_this_obj_p); + ecma_deref_object (proto_p); + + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + + ecma_value_t ret_value = ecma_op_function_call_native (func_obj_p, this_arg, arguments_list_p, arguments_list_len); + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + + if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) + { + ecma_deref_object (new_this_obj_p); + return ret_value; + } + + ecma_free_value (ret_value); + + return this_arg; +} /* ecma_op_function_construct_native */ + +/** + * General [[Construct]] implementation function objects + * + * See also: ECMAScript v6, 9.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); + + ECMA_CHECK_STACK_USAGE (); + + switch (ecma_get_object_type (func_obj_p)) + { + case ECMA_OBJECT_TYPE_FUNCTION: + { + return ecma_op_function_construct_simple (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + return ecma_op_function_construct_built_in (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + return ecma_proxy_object_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + return ecma_op_function_construct_constructor (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } + default: + { + JERRY_UNREACHABLE (); + } + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_function_construct */ + +/** + * Lazy instantiation of 'prototype' property for non-builtin and external functions + * + * @return pointer to newly instantiated property + */ +static ecma_property_t * +ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the function object */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION + || ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *global_object_p; + + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + global_object_p = ecma_op_function_get_realm (bytecode_data_p); + } + else + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; + + global_object_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); + } +#endif /* JERRY_BUILTIN_REALMS */ + + /* ECMA-262 v5, 13.2, 16-18 */ + + ecma_object_t *proto_object_p = NULL; + bool init_constructor = true; + + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + if (!CBC_FUNCTION_HAS_PROTOTYPE (byte_code_p->status_flags)) + { + return NULL; + } + + if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_GENERATOR) + { + ecma_object_t *prototype_p; + +#if JERRY_BUILTIN_REALMS + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); +#else /* !JERRY_BUILTIN_REALMS */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); +#endif /* JERRY_BUILTIN_REALMS */ + + proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + init_constructor = false; + } + + if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) + { + ecma_object_t *prototype_p; + +#if JERRY_BUILTIN_REALMS + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); +#else /* !JERRY_BUILTIN_REALMS */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); +#endif /* JERRY_BUILTIN_REALMS */ + + proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + init_constructor = false; + } + } + + if (proto_object_p == NULL) + { + ecma_object_t *prototype_p; + +#if JERRY_BUILTIN_REALMS + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#else /* !JERRY_BUILTIN_REALMS */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#endif /* JERRY_BUILTIN_REALMS */ + + proto_object_p = ecma_op_create_object_object_noarg_and_set_prototype (prototype_p); + } + + /* 17. */ + if (init_constructor) + { + ecma_property_value_t *constructor_prop_value_p; + constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + + constructor_prop_value_p->value = ecma_make_object_value (object_p); + } + + /* 18. */ + ecma_property_t *prototype_prop_p; + ecma_property_value_t *prototype_prop_value_p; + prototype_prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE), + ECMA_PROPERTY_BUILT_IN_WRITABLE, + &prototype_prop_p); + + prototype_prop_value_p->value = ecma_make_object_value (proto_object_p); + + ecma_deref_object (proto_object_p); + + return prototype_prop_p; +} /* ecma_op_lazy_instantiate_prototype_object */ + +/** + * Lazy instantiation of non-builtin ecma function object's properties + * + * Warning: + * Only non-configurable properties could be instantiated lazily in this function, + * as configurable properties could be deleted and it would be incorrect + * to reinstantiate them in the function in second time. + * + * @return pointer to newly instantiated property, if a property was instantiated, + * NULL - otherwise + */ +ecma_property_t * +ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION); + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + return NULL; + } + + /* Initialize 'length' property */ + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + uint32_t len; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_data_p); + + if (*extended_info_p & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + len = ecma_extended_info_decode_vlq (&extended_info_p); + } + } + + ecma_property_t *value_prop_p; + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &value_prop_p); + value_p->value = ecma_make_uint32_value (len); + return value_prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + return NULL; + } + + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_CONSTRUCTOR) + { + return NULL; + } + + ecma_value_t value = *ecma_compiled_code_resolve_function_name (bytecode_data_p); + JERRY_ASSERT (ecma_is_value_string (value)); + + /* Initialize 'name' property */ + ecma_property_t *value_prop_p; + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &value_prop_p); + value_p->value = ecma_copy_value (value); + return value_prop_p; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE) + && ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + return ecma_op_lazy_instantiate_prototype_object (object_p); + } + + const bool is_arguments = ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS); + + if (is_arguments || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)) + { + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) + && CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_NORMAL) + { + ecma_property_t *value_prop_p; + /* The property_name_p argument contains the name. */ + ecma_property_value_t *value_p = + ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_FIXED, &value_prop_p); + value_p->value = is_arguments ? ECMA_VALUE_NULL : ECMA_VALUE_UNDEFINED; + return value_prop_p; + } + } + + return NULL; +} /* ecma_op_function_try_to_lazy_instantiate_property */ + +/** + * Create specification defined non-configurable properties for external functions. + * + * See also: + * ECMA-262 v5, 15.3.4.5 + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + { + return ecma_op_lazy_instantiate_prototype_object (object_p); + } + + return NULL; +} /* ecma_op_external_function_try_to_lazy_instantiate_property */ + +/** + * Create specification defined non-configurable properties for bound functions. + * + * See also: + * ECMA-262 v5, 15.3.4.5 + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + if (ecma_string_is_length (property_name_p)) + { + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + ecma_number_t length = 0; + ecma_integer_value_t args_length = 1; + uint8_t length_attributes; + + if (ecma_is_value_integer_number (args_len_or_this)) + { + args_length = ecma_get_integer_from_value (args_len_or_this); + } + + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) + { + return NULL; + } + + length_attributes = ECMA_PROPERTY_BUILT_IN_CONFIGURABLE; + length = ecma_get_number_from_value (bound_func_p->target_length) - (args_length - 1); + + if (length < 0) + { + length = 0; + } + + ecma_property_t *len_prop_p; + ecma_property_value_t *len_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, length_attributes, &len_prop_p); + + len_prop_value_p->value = ecma_make_number_value (length); + return len_prop_p; + } + + return NULL; +} /* ecma_op_bound_function_try_to_lazy_instantiate_property */ + +/** + * Delete configurable properties of functions. + */ +void +ecma_op_function_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); + ECMA_SET_FIRST_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); + return; + } + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); + + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); +} /* ecma_op_function_delete_built_in_property */ + +/** + * Delete configurable properties of bound functions. + */ +void +ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_UNUSED (property_name_p); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)); + JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)); + + ECMA_SET_FIRST_BIT_TO_POINTER_TAG (bound_func_p->header.u.bound_function.target_function); +} /* ecma_op_bound_function_delete_built_in_property */ + +/** + * List names of a Function object's lazy instantiated properties, + * adding them to corresponding string collections + * + * See also: + * ecma_op_function_try_to_lazy_instantiate_property + */ +void +ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functionobject */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + + if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR + && !ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + /* Unintialized 'name' property is non-enumerable (ECMA-262 v6, 19.2.4.2) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_NAME)); + prop_counter_p->string_named_props++; + } + + if (!CBC_FUNCTION_HAS_PROTOTYPE (bytecode_data_p->status_flags) + || (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_CONSTRUCTOR)) + { + return; + } + + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)) + { + /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS)); + + /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); + + prop_counter_p->string_named_props += 2; + } + + /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); + prop_counter_p->string_named_props++; +} /* ecma_op_function_list_lazy_property_names */ + +/** + * List names of an External Function object's lazy instantiated properties, + * adding them to corresponding string collections + * + * See also: + * ecma_op_external_function_try_to_lazy_instantiate_property + */ +void +ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name + * filter options */ +{ + JERRY_UNUSED (object_p); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); + prop_counter_p->string_named_props++; +} /* ecma_op_external_function_list_lazy_property_names */ + +/** + * List names of a Bound Function object's lazy instantiated properties, + * adding them to corresponding string collections + * + * See also: + * ecma_op_bound_function_try_to_lazy_instantiate_property + */ +void +ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, /**< bound function object*/ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + + /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); + + /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS)); + + prop_counter_p->string_named_props += 2; +} /* ecma_op_bound_function_list_lazy_property_names */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.h new file mode 100644 index 00000000..08300f57 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-function-object.h @@ -0,0 +1,130 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_FUNCTION_OBJECT_H +#define ECMA_FUNCTION_OBJECT_H + +#include "ecma-builtin-handlers.h" +#include "ecma-builtins.h" +#include "ecma-globals.h" + +#include "vm.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmafunctionobject ECMA Function object related routines + * @{ + */ + +ecma_value_t ecma_op_function_form_name (ecma_string_t *prop_name_p, char *prefix_p, lit_utf8_size_t prefix_size); + +bool ecma_op_is_callable (ecma_value_t value); +#if JERRY_BUILTIN_PROXY +bool ecma_op_proxy_object_is_callable (ecma_object_t *obj_p); +#endif /* JERRY_BUILTIN_PROXY */ +bool ecma_op_object_is_callable (ecma_object_t *obj_p); +bool ecma_is_constructor (ecma_value_t value); +bool ecma_object_is_constructor (ecma_object_t *obj_p); + +/** + * Special constant indicating that the value is a valid constructor + * + * Use after the ecma_*_check_constructor calls. + */ + +ecma_error_msg_t ecma_object_check_constructor (ecma_object_t *obj_p); +ecma_error_msg_t ecma_check_constructor (ecma_value_t value); + +ecma_object_t *ecma_op_create_simple_function_object (ecma_object_t *scope_p, + const ecma_compiled_code_t *bytecode_data_p); + +ecma_object_t *ecma_op_create_external_function_object (ecma_native_handler_t handler_cb); + +const ecma_compiled_code_t *ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p); + +#if JERRY_BUILTIN_REALMS +ecma_global_object_t *ecma_op_function_get_realm (const ecma_compiled_code_t *bytecode_header_p); + +ecma_global_object_t *ecma_op_function_get_function_realm (ecma_object_t *func_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + +ecma_value_t ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + ecma_parse_opts_t opts); + +ecma_value_t ecma_op_function_get_super_constructor (ecma_object_t *func_obj_p); + +ecma_object_t *ecma_op_create_any_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p); + +ecma_object_t *ecma_op_create_arrow_function_object (ecma_object_t *scope_p, + const ecma_compiled_code_t *bytecode_data_p, + ecma_value_t this_binding); + +ecma_object_t *ecma_op_create_native_handler (ecma_native_handler_id_t id, size_t object_size); + +ecma_object_t *ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, ecma_builtin_id_t default_proto_id); + +ecma_value_t ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value); + +ecma_value_t ecma_op_function_validated_call (ecma_value_t callee, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_op_function_call (ecma_object_t *func_obj_p, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_op_function_construct (ecma_object_t *func_obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_property_t *ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +ecma_property_t *ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +ecma_property_t *ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, + ecma_string_t *property_name_p); + +void ecma_op_function_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +void ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +void ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +void ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +void ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +/** + * @} + * @} + */ + +#endif /* !ECMA_FUNCTION_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.cpp new file mode 100644 index 00000000..39d4d373 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.cpp @@ -0,0 +1,322 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of ECMA GetValue and PutValue + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-reference.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup lexicalenvironment Lexical environment + * @{ + */ + +/** + * GetValue operation part + * + * See also: ECMA-262 v5, 8.7.1, sections 3 and 5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_object_t **ref_base_lex_env_p, /**< [out] reference's base (lexical environment) */ + ecma_string_t *name_p) /**< variable name */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + while (true) + { + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + *ref_base_lex_env_p = lex_env_p; + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } + break; + } + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { +#if JERRY_MODULE_SYSTEM + if (ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + *ref_base_lex_env_p = lex_env_p; + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + property_value_p = ecma_get_property_value_from_named_reference (property_value_p); + } + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } + } +#endif /* JERRY_MODULE_SYSTEM */ + break; + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_value_t result = ecma_op_object_bound_environment_resolve_reference_value (lex_env_p, name_p); + + if (ecma_is_value_found (result)) + { + /* Note: the result may contains ECMA_VALUE_ERROR */ + *ref_base_lex_env_p = lex_env_p; + return result; + } + + break; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + *ref_base_lex_env_p = NULL; +#if JERRY_ERROR_MESSAGES + return ecma_raise_standard_error_with_format (JERRY_ERROR_REFERENCE, + "% is not defined", + ecma_make_string_value (name_p)); +#else /* JERRY_ERROR_MESSAGES */ + return ecma_raise_reference_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + +} /* ecma_op_get_value_lex_env_base */ + +/** + * GetValue operation part (object base). + * + * See also: ECMA-262 v5, 8.7.1, section 4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_object_t *obj_p; + + if (JERRY_UNLIKELY (ecma_is_value_object (base_value))) + { + obj_p = ecma_get_object_from_value (base_value); + } + else + { + ecma_builtin_id_t id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; + + if (JERRY_LIKELY (ecma_is_value_string (base_value))) + { + ecma_string_t *string_p = ecma_get_string_from_value (base_value); + + if (ecma_string_is_length (property_name_p)) + { + return ecma_make_uint32_value (ecma_string_get_length (string_p)); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX && index < ecma_string_get_length (string_p)) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (string_p, index); + return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (char_at_idx)); + } + +#if JERRY_BUILTIN_STRING + id = ECMA_BUILTIN_ID_STRING_PROTOTYPE; +#endif /* JERRY_BUILTIN_STRING */ + } + else if (ecma_is_value_number (base_value)) + { +#if JERRY_BUILTIN_NUMBER + id = ECMA_BUILTIN_ID_NUMBER_PROTOTYPE; +#endif /* JERRY_BUILTIN_NUMBER */ + } + else if (ecma_is_value_symbol (base_value)) + { + id = ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE; + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (base_value)) + { + id = ECMA_BUILTIN_ID_BIGINT_PROTOTYPE; + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + JERRY_ASSERT (ecma_is_value_boolean (base_value)); +#if JERRY_BUILTIN_BOOLEAN + id = ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE; +#endif /* JERRY_BUILTIN_BOOLEAN */ + } + + obj_p = ecma_builtin_get (id); + } + + return ecma_op_object_get_with_receiver (obj_p, property_name_p, base_value); +} /* ecma_op_get_value_object_base */ + +/** + * PutValue operation part + * + * See also: ECMA-262 v5, 8.7.2, sections 3 and 5 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< variable name */ + bool is_strict, /**< flag indicating strict mode */ + ecma_value_t value) /**< ECMA-value */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + while (true) + { + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { + if (!ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + break; + } + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_WRITABLE) || (*property_p & ECMA_PROPERTY_FLAG_DATA)); + + if ((*property_p & ECMA_PROPERTY_FLAG_WRITABLE) && property_value_p->value != ECMA_VALUE_UNINITIALIZED) + { + ecma_named_data_property_assign_value (lex_env_p, property_value_p, value); + return ECMA_VALUE_EMPTY; + } + + return ecma_op_raise_set_binding_error (property_p, is_strict); + } + break; + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t has_property = ecma_op_object_has_property (binding_obj_p, name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_property)) + { + return has_property; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (has_property)) + { + ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (ecma_is_value_boolean (completion)); + return ECMA_VALUE_EMPTY; + } + + break; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + if (is_strict) + { +#if JERRY_ERROR_MESSAGES + return ecma_raise_standard_error_with_format (JERRY_ERROR_REFERENCE, + "% is not defined", + ecma_make_string_value (name_p)); +#else /* !JERRY_ERROR_MESSAGES */ + return ecma_raise_reference_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + } + + ecma_value_t completion = ecma_op_object_put (ecma_get_lex_env_binding_object (lex_env_p), name_p, value, false); + + JERRY_ASSERT (ecma_is_value_boolean (completion)); + + return ECMA_VALUE_EMPTY; +} /* ecma_op_put_value_lex_env_base */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.cpp new file mode 100644 index 00000000..3e8ef7ea --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.cpp @@ -0,0 +1,719 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-iterator-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaiteratorobject ECMA iterator object related routines + * @{ + */ + +/** + * Implementation of 'CreateArrayFromList' specialized for iterators + * + * See also: + * ECMA-262 v6, 7.3.16. + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return new array object + */ +ecma_value_t +ecma_create_array_from_iter_element (ecma_value_t value, /**< value */ + ecma_value_t index_value) /**< iterator index */ +{ + /* 2. */ + ecma_object_t *new_array_p = ecma_op_new_array_object (0); + + /* 3-4. */ + ecma_value_t completion; + completion = + ecma_builtin_helper_def_prop_by_index (new_array_p, 0, index_value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + /* 4.b */ + JERRY_ASSERT (ecma_is_value_true (completion)); + + completion = + ecma_builtin_helper_def_prop_by_index (new_array_p, 1, value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (completion)); + + /* 5. */ + return ecma_make_object_value (new_array_p); +} /* ecma_create_array_from_iter_element */ + +/** + * CreateIterResultObject operation + * + * See also: + * ECMA-262 v6, 7.4.7. + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object + */ +ecma_value_t +ecma_create_iter_result_object (ecma_value_t value, /**< value */ + ecma_value_t done) /**< ECMA_VALUE_{TRUE,FALSE} based + * on the iterator index */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_boolean (done)); + + /* 2. */ + ecma_object_t *object_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 3. */ + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + prop_value_p->value = ecma_copy_value_if_not_object (value); + + /* 4. */ + prop_value_p = ecma_create_named_data_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_DONE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = done; + + /* 5. */ + return ecma_make_object_value (object_p); +} /* ecma_create_iter_result_object */ + +/** + * General iterator object creation operation. + * + * See also: ECMA-262 v6, 21.1.5.1, 22.1.5.1, 23.1.5.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object + */ +ecma_value_t +ecma_op_create_iterator_object (ecma_value_t iterated_value, /**< value from create iterator */ + ecma_object_t *prototype_obj_p, /**< prototype object */ + ecma_object_class_type_t iterator_type, /**< iterator type */ + ecma_iterator_kind_t kind) /**< iterator kind*/ +{ + /* 1. */ + JERRY_ASSERT (iterator_type == ECMA_OBJECT_CLASS_ARRAY_ITERATOR || iterator_type == ECMA_OBJECT_CLASS_SET_ITERATOR + || iterator_type == ECMA_OBJECT_CLASS_MAP_ITERATOR + || iterator_type == ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR + || iterator_type == ECMA_OBJECT_CLASS_STRING_ITERATOR); + JERRY_ASSERT (kind < ECMA_ITERATOR__COUNT); + + /* 2. */ + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.cls.type = (uint8_t) iterator_type; + + /* 3. */ + ext_obj_p->u.cls.u3.iterated_value = iterated_value; + /* 4. */ + ext_obj_p->u.cls.u2.iterator_index = 0; + /* 5. */ + ext_obj_p->u.cls.u1.iterator_kind = (uint8_t) kind; + + /* 6. */ + return ecma_make_object_value (object_p); +} /* ecma_op_create_iterator_object */ + +/** + * GetIterator operation + * + * See also: ECMA-262 v10, 7.4.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */ + ecma_value_t method, /**< provided method argument */ + ecma_value_t *next_method_p) /**< [out] next method */ +{ + JERRY_ASSERT (next_method_p != NULL); + *next_method_p = ECMA_VALUE_UNDEFINED; + + /* 1. */ + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + + bool use_default_method = false; + + /* 2. */ + if (method == ECMA_VALUE_SYNC_ITERATOR) + { + /* 2.a */ + use_default_method = true; + method = ecma_op_get_method_by_symbol_id (value, LIT_GLOBAL_SYMBOL_ITERATOR); + + /* 2.b */ + if (ECMA_IS_VALUE_ERROR (method)) + { + return method; + } + } + /* 3.a */ + else if (method == ECMA_VALUE_ASYNC_ITERATOR) + { + use_default_method = true; + + /* 3.a.i */ + method = ecma_op_get_method_by_symbol_id (value, LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (method)) + { + return method; + } + + /* 3.a.ii */ + + if (ecma_is_value_undefined (method)) + { + method = ecma_op_get_method_by_symbol_id (value, LIT_GLOBAL_SYMBOL_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (method)) + { + return method; + } + + ecma_value_t sync_next_method; + ecma_value_t sync_iterator = ecma_op_get_iterator (value, method, &sync_next_method); + + if (ECMA_IS_VALUE_ERROR (sync_iterator)) + { + ecma_free_value (method); + return sync_iterator; + } + + ecma_value_t async_iterator = + ecma_op_create_async_from_sync_iterator (sync_iterator, sync_next_method, next_method_p); + + ecma_free_value (method); + ecma_free_value (sync_iterator); + ecma_free_value (sync_next_method); + + return async_iterator; + } + } + + /* 3. */ + ecma_value_t iterator = ecma_op_function_validated_call (method, value, NULL, 0); + + if (use_default_method) + { + ecma_free_value (method); + } + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (iterator)) + { + return iterator; + } + + /* 5. */ + if (!ecma_is_value_object (iterator)) + { + ecma_free_value (iterator); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (iterator); + ecma_value_t next_method = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_NEXT); + + if (ECMA_IS_VALUE_ERROR (next_method)) + { + ecma_free_value (iterator); + return next_method; + } + + if (ecma_op_is_callable (next_method)) + { + *next_method_p = next_method; + } + else + { + ecma_free_value (next_method); + } + + /* 6. */ + return iterator; +} /* ecma_op_get_iterator */ + +/** + * IteratorNext operation + * + * See also: ECMA-262 v10, 7.4.2 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_iterator_next (ecma_value_t iterator, /**< iterator value */ + ecma_value_t next_method, /**< next method */ + ecma_value_t value) /**< the routines's value argument */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + /* 1 - 2. */ + if (next_method == ECMA_VALUE_UNDEFINED) + { + return ecma_raise_type_error (ECMA_ERR_ITERATOR_NEXT_IS_NOT_CALLABLE); + } + + ecma_object_t *next_method_obj_p = ecma_get_object_from_value (next_method); + + bool has_value = !ecma_is_value_empty (value); + + if (has_value) + { + return ecma_op_function_call (next_method_obj_p, iterator, &value, 1); + } + + return ecma_op_function_call (next_method_obj_p, iterator, NULL, 0); +} /* ecma_op_iterator_next */ + +/** + * IteratorReturn operation + * + * See also: ECMA-262 v6, 14.4.14 (last part) + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object - if success + * raised error - otherwise + */ +static ecma_value_t +ecma_op_iterator_return (ecma_value_t iterator, /**< iterator value */ + ecma_value_t value) /**< the routines's value argument */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + ecma_object_t *obj_p = ecma_get_object_from_value (iterator); + ecma_value_t func_return = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_RETURN); + + if (ECMA_IS_VALUE_ERROR (func_return)) + { + return func_return; + } + + if (func_return == ECMA_VALUE_UNDEFINED) + { + return ecma_create_iter_result_object (value, ECMA_VALUE_TRUE); + } + + ecma_value_t result = ecma_op_function_validated_call (func_return, iterator, &value, 1); + ecma_free_value (func_return); + + return result; +} /* ecma_op_iterator_return */ + +/** + * IteratorThrow operation + * + * See also: ECMA-262 v6, 14.4.14 (last part) + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object - if success + * raised error - otherwise + */ +static ecma_value_t +ecma_op_iterator_throw (ecma_value_t iterator, /**< iterator value */ + ecma_value_t value) /**< the routines's value argument */ +{ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + ecma_object_t *obj_p = ecma_get_object_from_value (iterator); + ecma_value_t func_throw = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_THROW); + + if (ECMA_IS_VALUE_ERROR (func_throw)) + { + return func_throw; + } + + if (func_throw == ECMA_VALUE_UNDEFINED) + { + ecma_value_t result = ecma_op_iterator_close (iterator); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE); + } + + ecma_value_t result = ecma_op_function_validated_call (func_throw, iterator, &value, 1); + ecma_free_value (func_throw); + + return result; +} /* ecma_op_iterator_throw */ + +/** + * IteratorComplete operation + * + * See also: ECMA-262 v10, 7.4.3 + * + * @return true/false - whether the iteration ended + */ +ecma_value_t +ecma_op_iterator_complete (ecma_value_t iter_result) /**< iterator value */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (iter_result)); + + /* 2. */ + ecma_object_t *obj_p = ecma_get_object_from_value (iter_result); + + ecma_value_t done = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (done)) + { + return done; + } + + ecma_value_t res = ecma_make_boolean_value (ecma_op_to_boolean (done)); + ecma_free_value (done); + + return res; +} /* ecma_op_iterator_complete */ + +/** + * IteratorValue operation + * + * See also: ECMA-262 v6, 7.4.4 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return value of the iterator result object + */ +ecma_value_t +ecma_op_iterator_value (ecma_value_t iter_result) /**< iterator value */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (iter_result)); + + /* 2. */ + ecma_object_t *obj_p = ecma_get_object_from_value (iter_result); + return ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_VALUE); +} /* ecma_op_iterator_value */ + +/** + * IteratorClose operation + * + * See also: ECMA-262 v6, 7.4.6 + * + * @return ECMA_VALUE_EMPTY - if "return" is succesfully invoked, + * and the operation is called with normal completion + * ECMA_VALUE_ERROR - otherwise + */ +ecma_value_t +ecma_op_iterator_close (ecma_value_t iterator) /**< iterator value */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (iterator)); + + /* 2. */ + ecma_value_t completion = ECMA_VALUE_EMPTY; + + if (jcontext_has_pending_exception ()) + { + completion = jcontext_take_exception (); + } + + /* 3. */ + ecma_value_t return_method = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (return_method)) + { + ecma_free_value (completion); + return return_method; + } + + /* 5. */ + if (ecma_is_value_undefined (return_method)) + { + if (ecma_is_value_empty (completion)) + { + return ECMA_VALUE_UNDEFINED; + } + + jcontext_raise_exception (completion); + return ECMA_VALUE_ERROR; + } + + /* 6. */ + ecma_object_t *return_obj_p = ecma_get_object_from_value (return_method); + ecma_value_t inner_result = ecma_op_function_call (return_obj_p, iterator, NULL, 0); + ecma_deref_object (return_obj_p); + + /* 7. */ + if (!ecma_is_value_empty (completion)) + { + if (ECMA_IS_VALUE_ERROR (inner_result)) + { + jcontext_release_exception (); + } + else + { + ecma_free_value (inner_result); + } + + jcontext_raise_exception (completion); + return ECMA_VALUE_ERROR; + } + + /* 8. */ + if (ECMA_IS_VALUE_ERROR (inner_result)) + { + ecma_free_value (completion); + return inner_result; + } + + /* 9. */ + bool is_object = ecma_is_value_object (inner_result); + ecma_free_value (inner_result); + + if (!is_object) + { + ecma_free_value (completion); + return ecma_raise_type_error (ECMA_ERR_METHOD_RETURN_IS_NOT_CALLABLE); + } + + /* 10. */ + if (ecma_is_value_empty (completion)) + { + return ECMA_VALUE_UNDEFINED; + } + + jcontext_raise_exception (completion); + return ECMA_VALUE_ERROR; +} /* ecma_op_iterator_close */ + +/** + * IteratorStep operation + * + * See also: ECMA-262 v6, 7.4.5 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object or ECMA_VALUE_FALSE - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_iterator_step (ecma_value_t iterator, /**< iterator value */ + ecma_value_t next_method) /**< next method */ +{ + /* 1. */ + ecma_value_t result = ecma_op_iterator_next (iterator, next_method, ECMA_VALUE_EMPTY); + + /* 2. */ + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT); + } + + /* 3. */ + ecma_object_t *obj_p = ecma_get_object_from_value (result); + ecma_value_t done = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_DONE); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (done)) + { + ecma_free_value (result); + return done; + } + + bool is_done = ecma_op_to_boolean (done); + ecma_free_value (done); + + /* 5. */ + if (is_done) + { + ecma_free_value (result); + return ECMA_VALUE_FALSE; + } + + /* 6. */ + return result; +} /* ecma_op_iterator_step */ + +/** + * Perform a command specified by the command argument + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_iterator_do (ecma_iterator_command_type_t command, /**< command to be executed */ + ecma_value_t iterator, /**< iterator object */ + ecma_value_t next_method, /**< next method */ + ecma_value_t value, /**< the routines's value argument */ + bool *done_p) /**< it contains the logical value of the done property */ +{ + ecma_value_t result; + + if (command == ECMA_ITERATOR_NEXT) + { + result = ecma_op_iterator_next (iterator, next_method, value); + } + else if (command == ECMA_ITERATOR_THROW) + { + result = ecma_op_iterator_throw (iterator, value); + } + else + { + JERRY_ASSERT (command == ECMA_ITERATOR_RETURN); + result = ecma_op_iterator_return (iterator, value); + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_object (result)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_RESULT_IS_NOT_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (result); + ecma_value_t done = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_DONE); + + if (ECMA_IS_VALUE_ERROR (done)) + { + ecma_free_value (result); + return done; + } + + *done_p = ecma_op_to_boolean (done); + ecma_free_value (done); + + return result; +} /* ecma_op_iterator_do */ + +/** + * CreateAsyncFromSyncIterator operation + * + * See also: ECMA-262 v10, 25.1.4.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return async from sync iterator object + */ +ecma_value_t +ecma_op_create_async_from_sync_iterator (ecma_value_t sync_iterator, /**< sync iterator */ + ecma_value_t sync_next_method, /**< sync iterator next method */ + ecma_value_t *async_next_method_p) /**< [out] async next method */ +{ + JERRY_ASSERT (ecma_is_value_object (sync_iterator)); + JERRY_ASSERT (ecma_is_value_object (sync_next_method) || ecma_is_value_undefined (sync_next_method)); + + /* 1. */ + ecma_object_t *obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE), + sizeof (ecma_async_from_sync_iterator_object_t), + ECMA_OBJECT_TYPE_CLASS); + + ecma_async_from_sync_iterator_object_t *ext_obj_p = (ecma_async_from_sync_iterator_object_t *) obj_p; + + /* 2. */ + ext_obj_p->sync_next_method = sync_next_method; + ext_obj_p->header.u.cls.u3.sync_iterator = sync_iterator; + ext_obj_p->header.u.cls.type = ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR; + + /* 3. */ + *async_next_method_p = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_NEXT); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (*async_next_method_p)); + + /* 4. */ + return ecma_make_object_value (obj_p); +} /* ecma_op_create_async_from_sync_iterator */ + +/** + * Async-from-Sync Iterator Value Unwrap Functions + * + * See also: ES11 25.1.4.2.4 + * + * @return iterator result object + */ +ecma_value_t +ecma_async_from_sync_iterator_unwrap_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_extended_object_t *unwrap_p = (ecma_extended_object_t *) function_obj_p; + + /* 2. */ + ecma_value_t arg = args_count > 0 ? args_p[0] : ECMA_VALUE_UNDEFINED; + ecma_value_t done = + ecma_make_boolean_value (unwrap_p->u.built_in.u2.routine_flags >> ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT); + + return ecma_create_iter_result_object (arg, done); +} /* ecma_async_from_sync_iterator_unwrap_cb */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.h new file mode 100644 index 00000000..0963b03f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-iterator-object.h @@ -0,0 +1,84 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_ITERATOR_OBJECT_H +#define ECMA_ITERATOR_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaiteratorobject ECMA iterator object related routines + * @{ + */ + +/** + * Generator resume execution flags. + */ +typedef enum +{ + ECMA_ITERATOR_NEXT, /**< generator should continue its execution */ + ECMA_ITERATOR_THROW, /**< generator should perform a throw operation */ + ECMA_ITERATOR_RETURN, /**< generator should perform a return operation */ +} ecma_iterator_command_type_t; + +/** + * Maximum value of [[%Iterator%NextIndex]] until it can be stored + * in an ecma pseudo array object structure element. + */ +#define ECMA_ITERATOR_INDEX_LIMIT UINT16_MAX + +ecma_value_t ecma_op_create_iterator_object (ecma_value_t iterated_value, + ecma_object_t *prototype_obj_p, + ecma_object_class_type_t iterator_type, + ecma_iterator_kind_t kind); + +ecma_value_t ecma_create_iter_result_object (ecma_value_t value, ecma_value_t done); + +ecma_value_t ecma_create_array_from_iter_element (ecma_value_t value, ecma_value_t index_value); + +ecma_value_t ecma_op_get_iterator (ecma_value_t value, ecma_value_t method, ecma_value_t *next_method_p); + +ecma_value_t ecma_op_iterator_complete (ecma_value_t iter_result); + +ecma_value_t ecma_op_iterator_value (ecma_value_t iter_result); + +ecma_value_t ecma_op_iterator_next (ecma_value_t iterator, ecma_value_t next_method, ecma_value_t value); + +ecma_value_t ecma_op_iterator_close (ecma_value_t iterator); + +ecma_value_t ecma_op_iterator_step (ecma_value_t iterator, ecma_value_t next_method); + +ecma_value_t ecma_op_iterator_do (ecma_iterator_command_type_t command, + ecma_value_t iterator, + ecma_value_t next_method, + ecma_value_t value, + bool *done_p); + +ecma_value_t ecma_op_create_async_from_sync_iterator (ecma_value_t sync_iterator, + ecma_value_t sync_next_method, + ecma_value_t *async_next_method_p); + +ecma_value_t ecma_async_from_sync_iterator_unwrap_cb (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +/** + * @} + * @} + */ + +#endif /* !ECMA_ITERATOR_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.cpp new file mode 100644 index 00000000..4826676b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.cpp @@ -0,0 +1,582 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-jobqueue.h" + +#include "ecma-async-generator-object.h" +#include "ecma-function-object.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "opcodes.h" +#include "vm-stack.h" + +/** + * Mask for job queue type. + */ +#define ECMA_JOB_QUEURE_TYPE_MASK ((uintptr_t) 0x07) + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmajobqueue ECMA Job Queue related routines + * @{ + */ + +/** + * Description of the PromiseReactionJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t capability; /**< capability object */ + ecma_value_t handler; /**< handler function */ + ecma_value_t argument; /**< argument for the reaction */ +} ecma_job_promise_reaction_t; + +/** + * Description of the PromiseAsyncReactionJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t executable_object; /**< executable object */ + ecma_value_t argument; /**< argument for the reaction */ +} ecma_job_promise_async_reaction_t; + +/** + * Description of the PromiseAsyncGeneratorJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t executable_object; /**< executable object */ +} ecma_job_promise_async_generator_t; + +/** + * Description of the PromiseResolveThenableJob + */ +typedef struct +{ + ecma_job_queue_item_t header; /**< job queue item header */ + ecma_value_t promise; /**< promise to be resolved */ + ecma_value_t thenable; /**< thenable object */ + ecma_value_t then; /**< 'then' function */ +} ecma_job_promise_resolve_thenable_t; + +/** + * Initialize the jobqueue. + */ +void +ecma_job_queue_init (void) +{ + JERRY_CONTEXT (job_queue_head_p) = NULL; + JERRY_CONTEXT (job_queue_tail_p) = NULL; +} /* ecma_job_queue_init */ + +/** + * Get the type of the job. + * + * @return type of the job + */ +static inline ecma_job_queue_item_type_t +ecma_job_queue_get_type (ecma_job_queue_item_t *job_p) /**< the job */ +{ + return (ecma_job_queue_item_type_t) (job_p->next_and_type & ECMA_JOB_QUEURE_TYPE_MASK); +} /* ecma_job_queue_get_type */ + +/** + * Get the next job of the job queue. + * + * @return next job + */ +static inline ecma_job_queue_item_t * +ecma_job_queue_get_next (ecma_job_queue_item_t *job_p) /**< the job */ +{ + return (ecma_job_queue_item_t *) (job_p->next_and_type & ~ECMA_JOB_QUEURE_TYPE_MASK); +} /* ecma_job_queue_get_next */ + +/** + * Free the heap and the member of the PromiseReactionJob. + */ +static void +ecma_free_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< points to the PromiseReactionJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->capability); + ecma_free_value (job_p->handler); + ecma_free_value (job_p->argument); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_reaction_t)); +} /* ecma_free_promise_reaction_job */ + +/** + * Free the heap and the member of the PromiseAsyncReactionJob. + */ +static void +ecma_free_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_p) /**< points to the + * PromiseAsyncReactionJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->executable_object); + ecma_free_value (job_p->argument); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_async_reaction_t)); +} /* ecma_free_promise_async_reaction_job */ + +/** + * Free the heap and the member of the PromiseAsyncGeneratorJob. + */ +static void +ecma_free_promise_async_generator_job (ecma_job_promise_async_generator_t *job_p) /**< points to the + * PromiseAsyncReactionJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->executable_object); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_async_generator_t)); +} /* ecma_free_promise_async_generator_job */ + +/** + * Free the heap and the member of the PromiseResolveThenableJob. + */ +static void +ecma_free_promise_resolve_thenable_job (ecma_job_promise_resolve_thenable_t *job_p) /**< points to the + * PromiseResolveThenableJob */ +{ + JERRY_ASSERT (job_p != NULL); + + ecma_free_value (job_p->promise); + ecma_free_value (job_p->thenable); + ecma_free_value (job_p->then); + + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_resolve_thenable_t)); +} /* ecma_free_promise_resolve_thenable_job */ + +/** + * The processor for PromiseReactionJob. + * + * See also: ES2015 25.4.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the job to be operated */ +{ + /* 2. */ + JERRY_ASSERT ( + ecma_object_class_is (ecma_get_object_from_value (job_p->capability), ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + ecma_promise_capabality_t *capability_p; + capability_p = (ecma_promise_capabality_t *) ecma_get_object_from_value (job_p->capability); + + /* 3. */ + ecma_value_t handler = job_p->handler; + + JERRY_ASSERT (ecma_is_value_boolean (handler) || ecma_op_is_callable (handler)); + + ecma_value_t handler_result; + + if (ecma_is_value_boolean (handler)) + { + /* 4-5. True indicates "identity" and false indicates "thrower" */ + handler_result = ecma_copy_value (job_p->argument); + } + else + { + /* 6. */ + handler_result = + ecma_op_function_call (ecma_get_object_from_value (handler), ECMA_VALUE_UNDEFINED, &(job_p->argument), 1); + } + + ecma_value_t status; + + if (ecma_is_value_false (handler) || ECMA_IS_VALUE_ERROR (handler_result)) + { + if (ECMA_IS_VALUE_ERROR (handler_result)) + { + handler_result = jcontext_take_exception (); + } + + /* 7. */ + status = ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), + ECMA_VALUE_UNDEFINED, + &handler_result, + 1); + } + else + { + /* 8. */ + status = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &handler_result, + 1); + } + + ecma_free_value (handler_result); + + ecma_free_promise_reaction_job (job_p); + + return status; +} /* ecma_process_promise_reaction_job */ + +/** + * The processor for PromiseAsyncReactionJob. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_p) /**< the job to be operated */ +{ + ecma_object_t *object_p = ecma_get_object_from_value (job_p->executable_object); + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + if (ecma_job_queue_get_type (&job_p->header) == ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED) + { + if (!(executable_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD)) + { + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + else if (ECMA_AWAIT_GET_STATE (executable_object_p) == ECMA_AWAIT_YIELD_RETURN) + { + /* Unlike other operations, return captures rejected promises as well. */ + ECMA_AWAIT_CHANGE_STATE (executable_object_p, YIELD_RETURN, YIELD_OPERATION); + } + else + { + if (ECMA_AWAIT_GET_STATE (executable_object_p) <= ECMA_AWAIT_YIELD_END) + { + JERRY_ASSERT (ecma_is_value_object (executable_object_p->iterator)); + executable_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (executable_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (executable_object_p->frame_ctx.stack_top_p[-1])); + executable_object_p->frame_ctx.stack_top_p--; + } + else if (ECMA_AWAIT_GET_STATE (executable_object_p) == ECMA_AWAIT_FOR_CLOSE + && VM_GET_CONTEXT_TYPE (executable_object_p->frame_ctx.stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW) + { + ecma_free_value (job_p->argument); + job_p->argument = ecma_copy_value (executable_object_p->frame_ctx.stack_top_p[-2]); + } + + /* Exception: Abort iterators, clear all status. */ + executable_object_p->extended_object.u.cls.u2.executable_obj_flags &= ECMA_AWAIT_CLEAR_MASK; + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + } + + ecma_value_t result; + uint16_t expected_bits; + + if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + job_p->argument = ecma_await_continue (executable_object_p, job_p->argument); + + if (ECMA_IS_VALUE_ERROR (job_p->argument)) + { + job_p->argument = jcontext_take_exception (); + executable_object_p->frame_ctx.byte_code_p = opfunc_resume_executable_object_with_throw; + } + else if (executable_object_p->extended_object.u.cls.u2.executable_obj_flags + & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD) + { + /* Continue iteration. */ + JERRY_ASSERT (job_p->argument == ECMA_VALUE_UNDEFINED); + result = ECMA_VALUE_UNDEFINED; + goto free_job; + } + + if (ECMA_AWAIT_GET_STATE (executable_object_p) <= ECMA_AWAIT_YIELD_END) + { + JERRY_ASSERT (ecma_is_value_object (executable_object_p->iterator)); + executable_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (executable_object_p->frame_ctx.stack_top_p[-1] == ECMA_VALUE_UNDEFINED + || ecma_is_value_object (executable_object_p->frame_ctx.stack_top_p[-1])); + executable_object_p->frame_ctx.stack_top_p--; + } + + /* Clear all status. */ + executable_object_p->extended_object.u.cls.u2.executable_obj_flags &= ECMA_AWAIT_CLEAR_MASK; + } + + result = opfunc_resume_executable_object (executable_object_p, job_p->argument); + /* Argument reference has been taken by opfunc_resume_executable_object. */ + job_p->argument = ECMA_VALUE_UNDEFINED; + + expected_bits = (ECMA_EXECUTABLE_OBJECT_COMPLETED | ECMA_ASYNC_GENERATOR_CALLED); + if ((executable_object_p->extended_object.u.cls.u2.executable_obj_flags & expected_bits) == expected_bits) + { + ecma_async_generator_finalize (executable_object_p, result); + result = ECMA_VALUE_UNDEFINED; + } + +free_job: + + ecma_free_promise_async_reaction_job (job_p); + return result; +} /* ecma_process_promise_async_reaction_job */ + +/** + * The processor for PromiseAsyncGeneratorJob. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_async_generator_job (ecma_job_promise_async_generator_t *job_p) /**< the job to be operated */ +{ + ecma_object_t *object_p = ecma_get_object_from_value (job_p->executable_object); + + ecma_value_t result = ecma_async_generator_run ((vm_executable_object_t *) object_p); + + ecma_free_value (job_p->executable_object); + jmem_heap_free_block (job_p, sizeof (ecma_job_promise_async_generator_t)); + return result; +} /* ecma_process_promise_async_generator_job */ + +/** + * Process the PromiseResolveThenableJob. + * + * See also: ES2015 25.4.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_process_promise_resolve_thenable_job (ecma_job_promise_resolve_thenable_t *job_p) /**< the job to be operated */ +{ + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) ecma_get_object_from_value (job_p->promise); + + promise_p->header.u.cls.u1.promise_flags &= (uint8_t) ~ECMA_PROMISE_ALREADY_RESOLVED; + + ecma_value_t ret = ecma_promise_run_executor ((ecma_object_t *) promise_p, job_p->then, job_p->thenable); + + if (ECMA_IS_VALUE_ERROR (ret)) + { + ret = jcontext_take_exception (); + ecma_reject_promise_with_checks (job_p->promise, ret); + ecma_free_value (ret); + ret = ECMA_VALUE_UNDEFINED; + } + + ecma_free_promise_resolve_thenable_job (job_p); + + return ret; +} /* ecma_process_promise_resolve_thenable_job */ + +/** + * Enqueue a Promise job into the jobqueue. + */ +static void +ecma_enqueue_job (ecma_job_queue_item_t *job_p) /**< the job */ +{ + JERRY_ASSERT (job_p->next_and_type <= ECMA_JOB_QUEURE_TYPE_MASK); + + if (JERRY_CONTEXT (job_queue_head_p) == NULL) + { + JERRY_CONTEXT (job_queue_head_p) = job_p; + JERRY_CONTEXT (job_queue_tail_p) = job_p; + } + else + { + JERRY_ASSERT ((JERRY_CONTEXT (job_queue_tail_p)->next_and_type & ~ECMA_JOB_QUEURE_TYPE_MASK) == 0); + + JERRY_CONTEXT (job_queue_tail_p)->next_and_type |= (uintptr_t) job_p; + JERRY_CONTEXT (job_queue_tail_p) = job_p; + } +} /* ecma_enqueue_job */ + +/** + * Enqueue a PromiseReactionJob into the job queue. + */ +void +ecma_enqueue_promise_reaction_job (ecma_value_t capability, /**< capability object */ + ecma_value_t handler, /**< handler function */ + ecma_value_t argument) /**< argument for the reaction */ +{ + ecma_job_promise_reaction_t *job_p; + job_p = (ecma_job_promise_reaction_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_reaction_t)); + job_p->header.next_and_type = ECMA_JOB_PROMISE_REACTION; + job_p->capability = ecma_copy_value (capability); + job_p->handler = ecma_copy_value (handler); + job_p->argument = ecma_copy_value (argument); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_reaction_job */ + +/** + * Enqueue a PromiseAsyncReactionJob into the job queue. + */ +void +ecma_enqueue_promise_async_reaction_job (ecma_value_t executable_object, /**< executable object */ + ecma_value_t argument, /**< argument */ + bool is_rejected) /**< is_fulfilled */ +{ + ecma_job_promise_async_reaction_t *job_p; + job_p = (ecma_job_promise_async_reaction_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_async_reaction_t)); + job_p->header.next_and_type = + (is_rejected ? ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED : ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED); + job_p->executable_object = ecma_copy_value (executable_object); + job_p->argument = ecma_copy_value (argument); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_async_reaction_job */ + +/** + * Enqueue a PromiseAsyncGeneratorJob into the job queue. + */ +void +ecma_enqueue_promise_async_generator_job (ecma_value_t executable_object) /**< executable object */ +{ + ecma_job_promise_async_generator_t *job_p; + job_p = (ecma_job_promise_async_generator_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_async_generator_t)); + job_p->header.next_and_type = ECMA_JOB_PROMISE_ASYNC_GENERATOR; + job_p->executable_object = ecma_copy_value (executable_object); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_async_generator_job */ + +/** + * Enqueue a PromiseResolveThenableJob into the job queue. + */ +void +ecma_enqueue_promise_resolve_thenable_job (ecma_value_t promise, /**< promise to be resolved */ + ecma_value_t thenable, /**< thenable object */ + ecma_value_t then) /**< 'then' function */ +{ + JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise))); + JERRY_ASSERT (ecma_is_value_object (thenable)); + JERRY_ASSERT (ecma_op_is_callable (then)); + + ecma_job_promise_resolve_thenable_t *job_p; + job_p = (ecma_job_promise_resolve_thenable_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_resolve_thenable_t)); + job_p->header.next_and_type = ECMA_JOB_PROMISE_THENABLE; + job_p->promise = ecma_copy_value (promise); + job_p->thenable = ecma_copy_value (thenable); + job_p->then = ecma_copy_value (then); + + ecma_enqueue_job (&job_p->header); +} /* ecma_enqueue_promise_resolve_thenable_job */ + +/** + * Process enqueued Promise jobs until the first thrown error or until the + * jobqueue becomes empty. + * + * @return result of the last processed job - if the jobqueue was non-empty, + * undefined - otherwise. + */ +ecma_value_t +ecma_process_all_enqueued_jobs (void) +{ + ecma_value_t ret = ECMA_VALUE_UNDEFINED; + + while (JERRY_CONTEXT (job_queue_head_p) != NULL) + { + ecma_job_queue_item_t *job_p = JERRY_CONTEXT (job_queue_head_p); + JERRY_CONTEXT (job_queue_head_p) = ecma_job_queue_get_next (job_p); + + ecma_fast_free_value (ret); + + switch (ecma_job_queue_get_type (job_p)) + { + case ECMA_JOB_PROMISE_REACTION: + { + ret = ecma_process_promise_reaction_job ((ecma_job_promise_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED: + case ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED: + { + ret = ecma_process_promise_async_reaction_job ((ecma_job_promise_async_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_GENERATOR: + { + ret = ecma_process_promise_async_generator_job ((ecma_job_promise_async_generator_t *) job_p); + break; + } + default: + { + JERRY_ASSERT (ecma_job_queue_get_type (job_p) == ECMA_JOB_PROMISE_THENABLE); + + ret = ecma_process_promise_resolve_thenable_job ((ecma_job_promise_resolve_thenable_t *) job_p); + break; + } + } + + if (ECMA_IS_VALUE_ERROR (ret)) + { + return ret; + } + } + + ecma_free_value (ret); + return ECMA_VALUE_UNDEFINED; +} /* ecma_process_all_enqueued_jobs */ + +/** + * Release enqueued Promise jobs. + */ +void +ecma_free_all_enqueued_jobs (void) +{ + while (JERRY_CONTEXT (job_queue_head_p) != NULL) + { + ecma_job_queue_item_t *job_p = JERRY_CONTEXT (job_queue_head_p); + JERRY_CONTEXT (job_queue_head_p) = ecma_job_queue_get_next (job_p); + + switch (ecma_job_queue_get_type (job_p)) + { + case ECMA_JOB_PROMISE_REACTION: + { + ecma_free_promise_reaction_job ((ecma_job_promise_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED: + case ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED: + { + ecma_free_promise_async_reaction_job ((ecma_job_promise_async_reaction_t *) job_p); + break; + } + case ECMA_JOB_PROMISE_ASYNC_GENERATOR: + { + ecma_free_promise_async_generator_job ((ecma_job_promise_async_generator_t *) job_p); + break; + } + default: + { + JERRY_ASSERT (ecma_job_queue_get_type (job_p) == ECMA_JOB_PROMISE_THENABLE); + + ecma_free_promise_resolve_thenable_job ((ecma_job_promise_resolve_thenable_t *) job_p); + break; + } + } + } +} /* ecma_free_all_enqueued_jobs */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.h new file mode 100644 index 00000000..b56027ca --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-jobqueue.h @@ -0,0 +1,63 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_JOB_QUEUE_H +#define ECMA_JOB_QUEUE_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmajobqueue ECMA Job Queue related routines + * @{ + */ + +/** + * Job queue item types. + */ +typedef enum +{ + ECMA_JOB_PROMISE_REACTION, /**< promise reaction job */ + ECMA_JOB_PROMISE_ASYNC_REACTION_FULFILLED, /**< fulfilled promise async reaction job */ + ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED, /**< rejected promise async reaction job */ + ECMA_JOB_PROMISE_ASYNC_GENERATOR, /**< continue async generator */ + ECMA_JOB_PROMISE_THENABLE, /**< promise thenable job */ +} ecma_job_queue_item_type_t; + +/** + * Description of the job queue item. + */ +typedef struct +{ + uintptr_t next_and_type; /**< next and type members of a queue item */ +} ecma_job_queue_item_t; + +void ecma_job_queue_init (void); + +void ecma_enqueue_promise_reaction_job (ecma_value_t capability, ecma_value_t handler, ecma_value_t argument); +void ecma_enqueue_promise_async_reaction_job (ecma_value_t executable_object, ecma_value_t argument, bool is_rejected); +void ecma_enqueue_promise_async_generator_job (ecma_value_t executable_object); +void ecma_enqueue_promise_resolve_thenable_job (ecma_value_t promise, ecma_value_t thenable, ecma_value_t then); +void ecma_free_all_enqueued_jobs (void); + +ecma_value_t ecma_process_all_enqueued_jobs (void); + +/** + * @} + * @} + */ + +#endif /* !ECMA_JOB_QUEUE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.cpp new file mode 100644 index 00000000..0b04a38f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.cpp @@ -0,0 +1,643 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-lex-env.h" + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup lexicalenvironment Lexical environment + * @{ + * + * \addtogroup globallexicalenvironment Global lexical environment + * @{ + */ + +/** + * Initialize Global environment + */ +void +ecma_init_global_environment (void) +{ + JERRY_CONTEXT (global_object_p) = ecma_builtin_create_global_object (); +} /* ecma_init_global_environment */ + +/** + * Finalize Global environment + */ +void +ecma_finalize_global_environment (void) +{ + /* After this point the gc can free the global object, but the global_object_p pointer + * is not set to NULL because the global object might still be used before the free. */ + ecma_deref_object ((ecma_object_t *) JERRY_CONTEXT (global_object_p)); +} /* ecma_finalize_global_environment */ + +/** + * Get reference to Global lexical environment + * without increasing its reference count. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_get_global_environment (ecma_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p)); + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, ((ecma_global_object_t *) global_object_p)->global_env_cp); +} /* ecma_get_global_environment */ + +/** + * Create the global lexical block on top of the global environment. + */ +void +ecma_create_global_lexical_block (ecma_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p)); + + ecma_global_object_t *real_global_object_p = (ecma_global_object_t *) global_object_p; + + if (real_global_object_p->global_scope_cp == real_global_object_p->global_env_cp) + { + ecma_object_t *global_scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p)); + global_scope_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + ECMA_SET_NON_NULL_POINTER (real_global_object_p->global_scope_cp, global_scope_p); + ecma_deref_object (global_scope_p); + } +} /* ecma_create_global_lexical_block */ + +/** + * Raise the appropriate error when setting a binding is failed + * + * @return ECMA_VALUE_EMPTY or ECMA_VALUE_ERROR + */ +ecma_value_t +ecma_op_raise_set_binding_error (ecma_property_t *property_p, /**< property */ + bool is_strict) /**< flag indicating strict mode */ +{ + JERRY_UNUSED (property_p); + + const ecma_property_t expected_bits = (ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_ENUMERABLE); + + if ((*property_p & expected_bits) == expected_bits) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + JERRY_ASSERT (!ecma_is_property_writable (*property_p)); + + return ecma_raise_type_error (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED); + } + + if (is_strict) + { + return ecma_raise_type_error (ECMA_ERR_BINDING_CANNOT_SET); + } + return ECMA_VALUE_EMPTY; +} /* ecma_op_raise_set_binding_error */ + +/** + * Get reference to Global lexical scope + * without increasing its reference count. + * + * @return pointer to the object's instance + */ +ecma_object_t * +ecma_get_global_scope (ecma_object_t *global_object_p) /**< global object */ +{ + JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p)); + return ECMA_GET_NON_NULL_POINTER (ecma_object_t, ((ecma_global_object_t *) global_object_p)->global_scope_cp); +} /* ecma_get_global_scope */ + +/** + * @} + */ + +/** + * HasBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return true / false + */ +ecma_value_t +ecma_op_has_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p) /**< argument N */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + ecma_lexical_environment_type_t lex_env_type = ecma_get_lex_env_type (lex_env_p); + + switch (lex_env_type) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { + if (!ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + return ECMA_VALUE_FALSE; + } + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + return ecma_make_boolean_value (property_p != NULL); + } + default: + { + JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + return ecma_op_object_has_property (binding_obj_p, name_p); + } + } +} /* ecma_op_has_binding */ + +/** + * CreateMutableBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ECMA_PROPERTY_POINTER_ERROR - if the operation raises error + * pointer to the created property - if the binding was created into a declerative environment + * NULL - otherwise + */ +ecma_property_t * +ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + bool is_deletable) /**< argument D */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (is_deletable) + { + prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_CONFIGURABLE); + } + + ecma_property_t *prop_p; + + ecma_create_named_data_property (lex_env_p, name_p, prop_attributes, &prop_p); + return prop_p; + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + +#if JERRY_BUILTIN_PROXY && JERRY_BUILTIN_REALMS + if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + ecma_value_t result = ecma_proxy_object_is_extensible (binding_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return ECMA_PROPERTY_POINTER_ERROR; + } + + if (result == ECMA_VALUE_FALSE) + { + return NULL; + } + } + else if (!ecma_op_ordinary_object_is_extensible (binding_obj_p)) + { + return NULL; + } +#else /* !JERRY_BUILTIN_PROXY || !JERRY_BUILTIN_REALMS */ + if (!ecma_op_ordinary_object_is_extensible (binding_obj_p)) + { + return NULL; + } +#endif /* JERRY_BUILTIN_PROXY && JERRY_BUILTIN_REALMS */ + + const uint32_t flags = ECMA_PROPERTY_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + + ecma_value_t completion = + ecma_builtin_helper_def_prop (binding_obj_p, + name_p, + ECMA_VALUE_UNDEFINED, + is_deletable ? flags | ECMA_PROPERTY_FLAG_CONFIGURABLE : flags); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return ECMA_PROPERTY_POINTER_ERROR; + } + else + { + JERRY_ASSERT (ecma_is_value_boolean (completion)); + } + } + + return NULL; +} /* ecma_op_create_mutable_binding */ + +/** + * SetMutableBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + ecma_value_t value, /**< argument V */ + bool is_strict) /**< argument S */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { + if (!ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + return ECMA_VALUE_EMPTY; + } + /* FALLTHRU */ + } + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (JERRY_UNLIKELY (property_p == NULL)) + { + property_p = ecma_op_create_mutable_binding (lex_env_p, name_p, is_strict); + JERRY_ASSERT (property_p != ECMA_PROPERTY_POINTER_ERROR); + } + + JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p)); + JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_WRITABLE) || (*property_p & ECMA_PROPERTY_FLAG_DATA)); + + if ((*property_p & ECMA_PROPERTY_FLAG_WRITABLE)) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + JERRY_ASSERT (property_value_p->value != ECMA_VALUE_UNINITIALIZED); + + ecma_named_data_property_assign_value (lex_env_p, property_value_p, value); + return ECMA_VALUE_EMPTY; + } + + return ecma_op_raise_set_binding_error (property_p, is_strict); + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (ecma_is_value_boolean (completion)); + return ECMA_VALUE_EMPTY; + } + } +} /* ecma_op_set_mutable_binding */ + +/** + * GetBindingValue operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + bool is_strict) /**< argument S */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_value_t *prop_value_p = ecma_get_named_data_property (lex_env_p, name_p); + + return ecma_copy_value (prop_value_p->value); + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t result = ecma_op_object_find (binding_obj_p, name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_found (result)) + { + if (is_strict) + { + result = ecma_raise_reference_error (ECMA_ERR_BINDING_NOT_EXIST_OR_UNINITIALIZED); + } + else + { + result = ECMA_VALUE_UNDEFINED; + } + } + + return result; + } +} /* ecma_op_get_binding_value */ + +/** + * DeleteBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the binding can be deleted + */ +ecma_value_t +ecma_op_delete_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p) /**< argument N */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (name_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *prop_p = ecma_find_named_property (lex_env_p, name_p); + ecma_value_t ret_val; + + if (prop_p == NULL) + { + ret_val = ECMA_VALUE_TRUE; + } + else + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (*prop_p)); + + if (!ecma_is_property_configurable (*prop_p)) + { + ret_val = ECMA_VALUE_FALSE; + } + else + { + ecma_delete_property (lex_env_p, ECMA_PROPERTY_VALUE_PTR (prop_p)); + + ret_val = ECMA_VALUE_TRUE; + } + } + + return ret_val; + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + return ecma_op_object_delete (binding_obj_p, name_p, false); + } +} /* ecma_op_delete_binding */ + +/** + * ImplicitThisValue operation. + * + * See also: ECMA-262 v5, 10.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_implicit_this_value (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + return ECMA_VALUE_UNDEFINED; + } + else + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + ecma_ref_object (binding_obj_p); + + return ecma_make_object_value (binding_obj_p); + } +} /* ecma_op_implicit_this_value */ + +/** + * CreateImmutableBinding operation. + * + * See also: ECMA-262 v5, 10.2.1 + */ +void +ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + ecma_value_t value) /**< argument V */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + /* + * Warning: + * Whether immutable bindings are deletable seems not to be defined by ECMA v5. + */ + ecma_property_value_t *prop_value_p = ecma_create_named_data_property (lex_env_p, name_p, ECMA_PROPERTY_FIXED, NULL); + + prop_value_p->value = ecma_copy_value_if_not_object (value); +} /* ecma_op_create_immutable_binding */ + +/** + * InitializeBinding operation. + * + * See also: ECMA-262 v6, 8.1.1.1.4 + */ +void +ecma_op_initialize_binding (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< argument N */ + ecma_value_t value) /**< argument V */ +{ + JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + ecma_property_t *prop_p = ecma_find_named_property (lex_env_p, name_p); + JERRY_ASSERT (prop_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*prop_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p); + JERRY_ASSERT (prop_value_p->value == ECMA_VALUE_UNINITIALIZED); + + prop_value_p->value = ecma_copy_value_if_not_object (value); +} /* ecma_op_initialize_binding */ + +/** + * BindThisValue operation for an empty lexical environment + * + * See also: ECMA-262 v6, 8.1.1.3.1 + */ +void +ecma_op_create_environment_record (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_value_t this_binding, /**< this binding value */ + ecma_object_t *func_obj_p) /**< function object */ +{ + JERRY_ASSERT (lex_env_p != NULL); + JERRY_ASSERT (ecma_is_value_object (this_binding) || this_binding == ECMA_VALUE_UNINITIALIZED); + + ecma_environment_record_t *environment_record_p; + environment_record_p = (ecma_environment_record_t *) jmem_heap_alloc_block (sizeof (ecma_environment_record_t)); + + environment_record_p->this_binding = this_binding; + environment_record_p->function_object = ecma_make_object_value (func_obj_p); + + ecma_string_t *property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD); + + ecma_property_t *property_p; + ecma_property_value_t *prop_value_p; + ECMA_CREATE_INTERNAL_PROPERTY (lex_env_p, property_name_p, property_p, prop_value_p); + + ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, environment_record_p); +} /* ecma_op_create_environment_record */ + +/** + * GetThisEnvironment operation. + * + * See also: ECMA-262 v6, 8.3.2 + * + * @return property pointer for the internal [[ThisBindingValue]] property + */ +ecma_environment_record_t * +ecma_op_get_environment_record (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + ecma_string_t *property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD); + while (true) + { + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, property_name_p); + + if (property_p != NULL) + { + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t, property_value_p->value); + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + return NULL; +} /* ecma_op_get_environment_record */ + +/** + * Get the environment record [[ThisBindingStatus]] internal property. + * + * See also: ECMA-262 v6, 8.1.1.3 + * + * @return true - if the status is "initialzed" + * false - otherwise + */ +bool +ecma_op_this_binding_is_initialized (ecma_environment_record_t *environment_record_p) /**< environment record */ +{ + JERRY_ASSERT (environment_record_p != NULL); + + return environment_record_p->this_binding != ECMA_VALUE_UNINITIALIZED; +} /* ecma_op_this_binding_is_initialized */ + +/** + * BindThisValue operation. + * + * See also: ECMA-262 v6, 8.1.1.3.1 + */ +void +ecma_op_bind_this_value (ecma_environment_record_t *environment_record_p, /**< environment record */ + ecma_value_t this_binding) /**< this binding value */ +{ + JERRY_ASSERT (environment_record_p != NULL); + JERRY_ASSERT (ecma_is_value_object (this_binding)); + JERRY_ASSERT (!ecma_op_this_binding_is_initialized (environment_record_p)); + + environment_record_p->this_binding = this_binding; +} /* ecma_op_bind_this_value */ + +/** + * GetThisBinding operation. + * + * See also: ECMA-262 v6, 8.1.1.3.4 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ecma-object - otherwise + */ +ecma_value_t +ecma_op_get_this_binding (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (lex_env_p); + JERRY_ASSERT (environment_record_p != NULL); + + ecma_value_t this_value = environment_record_p->this_binding; + + if (this_value == ECMA_VALUE_UNINITIALIZED) + { + return ecma_raise_reference_error (ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS); + } + + ecma_ref_object (ecma_get_object_from_value (this_value)); + + return this_value; +} /* ecma_op_get_this_binding */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.h new file mode 100644 index 00000000..e71d729f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-lex-env.h @@ -0,0 +1,85 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_LEX_ENV_H +#define ECMA_LEX_ENV_H + +#include "ecma-globals.h" +#include "ecma-reference.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup lexicalenvironment Lexical environment + * @{ + * + * \addtogroup globallexicalenvironment Global lexical environment + * @{ + */ + +void ecma_init_global_environment (void); +void ecma_finalize_global_environment (void); +ecma_object_t *ecma_get_global_environment (ecma_object_t *global_object_p); +ecma_object_t *ecma_get_global_scope (ecma_object_t *global_object_p); +void ecma_create_global_lexical_block (ecma_object_t *global_object_p); +ecma_value_t ecma_op_raise_set_binding_error (ecma_property_t *property_p, bool is_strict); + +#if JERRY_MODULE_SYSTEM +void ecma_module_add_lex_env (ecma_object_t *lex_env_p); +void ecma_module_finalize_lex_envs (void); +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * @} + */ + +/* ECMA-262 v5, 8.7.1 and 8.7.2 */ +ecma_value_t +ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, ecma_object_t **ref_base_lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_get_value_object_base (ecma_value_t base_value, ecma_string_t *property_name_p); +ecma_value_t ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, + ecma_string_t *var_name_string_p, + bool is_strict, + ecma_value_t value); + +/* ECMA-262 v5, Table 17. Abstract methods of Environment Records */ +ecma_value_t ecma_op_has_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_property_t *ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, bool is_deletable); +ecma_value_t +ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value, bool is_strict); +ecma_value_t ecma_op_get_binding_value (ecma_object_t *lex_env_p, ecma_string_t *name_p, bool is_strict); +ecma_value_t ecma_op_delete_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_implicit_this_value (ecma_object_t *lex_env_p); + +/* ECMA-262 v5, Table 18. Additional methods of Declarative Environment Records */ +void ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value); + +void ecma_op_initialize_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value); + +void ecma_op_create_environment_record (ecma_object_t *lex_env_p, ecma_value_t this_binding, ecma_object_t *func_obj_p); +ecma_environment_record_t *ecma_op_get_environment_record (ecma_object_t *lex_env_p); + +bool ecma_op_this_binding_is_initialized (ecma_environment_record_t *environment_record_p); +void ecma_op_bind_this_value (ecma_environment_record_t *environment_record_p, ecma_value_t this_binding); +ecma_value_t ecma_op_get_this_binding (ecma_object_t *lex_env_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_LEX_ENV_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.cpp new file mode 100644 index 00000000..548f2f73 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.cpp @@ -0,0 +1,95 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-number-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmanumberobject ECMA Number object related routines + * @{ + */ + +/** + * Number object creation operation. + * + * See also: ECMA-262 v5, 15.7.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ +{ + ecma_number_t num; + ecma_value_t conv_to_num_completion = ecma_op_to_number (arg, &num); + + if (ECMA_IS_VALUE_ERROR (conv_to_num_completion)) + { + return conv_to_num_completion; + } + + conv_to_num_completion = ecma_make_number_value (num); + ecma_builtin_id_t proto_id; +#if JERRY_BUILTIN_NUMBER + proto_id = ECMA_BUILTIN_ID_NUMBER_PROTOTYPE; +#else /* JERRY_BUILTIN_NUMBER */ + proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; +#endif /* JERRY_BUILTIN_NUMBER */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + ecma_object_t *new_target = JERRY_CONTEXT (current_new_target_p); + if (new_target) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (new_target, proto_id); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_NUMBER; + + /* Pass reference (no need to free conv_to_num_completion). */ + ext_object_p->u.cls.u3.value = conv_to_num_completion; + + if (new_target) + { + ecma_deref_object (prototype_obj_p); + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_number_object */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.h new file mode 100644 index 00000000..c4baf75f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-number-object.h @@ -0,0 +1,35 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_NUMBER_OBJECT_H +#define ECMA_NUMBER_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmanumberobject ECMA Number object related routines + * @{ + */ + +ecma_value_t ecma_op_create_number_object (ecma_value_t arg); + +/** + * @} + * @} + */ + +#endif /* !ECMA_NUMBER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.cpp new file mode 100644 index 00000000..f4425c83 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.cpp @@ -0,0 +1,753 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-objects-general.h" + +#include "ecma-arguments-object.h" +#include "ecma-array-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +/** + * 'Object' object creation operation with no arguments. + * + * See also: ECMA-262 v5, 15.2.2.1 + * + * @return pointer to newly created 'Object' object + */ +ecma_object_t * +ecma_op_create_object_object_noarg (void) +{ + ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + /* 3., 4., 6., 7. */ + return ecma_op_create_object_object_noarg_and_set_prototype (object_prototype_p); +} /* ecma_op_create_object_object_noarg */ + +/** + * Object creation operation with no arguments. + * It sets the given prototype to the newly created object. + * + * See also: ECMA-262 v5, 15.2.2.1, 15.2.3.5 + * + * @return pointer to newly created object + */ +ecma_object_t * +ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p) /**< pointer to prototype of + the object + (can be NULL) */ +{ + ecma_object_t *obj_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + /* + * [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects + * without ECMA_INTERNAL_PROPERTY_CLASS internal property + * is "Object". + * + * See also: ecma_object_get_class_name + */ + + return obj_p; +} /* ecma_op_create_object_object_noarg_and_set_prototype */ + +/** + * [[Delete]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_throw) /**< flag that controls failure handling */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (property_name_p != NULL); + + /* 1. */ + ecma_property_ref_t property_ref; + + ecma_property_t property = + ecma_op_object_get_own_property (obj_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_NO_OPTIONS); + + /* 2. */ + if (!ECMA_PROPERTY_IS_FOUND (property)) + { + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + return ECMA_VALUE_TRUE; + } + + /* 3. */ + if (!ecma_is_property_configurable (property)) + { + /* 4. */ + if (is_throw) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY); + } + + /* 5. */ + return ECMA_VALUE_FALSE; + } + + ecma_object_type_t type = ecma_get_object_type (obj_p); + + if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_array_object_delete_property (obj_p, property_name_p)) + { + return ECMA_VALUE_TRUE; + } + + /* a. */ + ecma_delete_property (obj_p, property_ref.value_p); + + if (property & ECMA_PROPERTY_FLAG_BUILT_IN) + { + switch (type) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (obj_p)) + { + ecma_builtin_routine_delete_built_in_property (obj_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ecma_builtin_delete_built_in_property (obj_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + ecma_op_arguments_delete_built_in_property (obj_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + ecma_op_function_delete_built_in_property (obj_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_op_bound_function_delete_built_in_property (obj_p, property_name_p); + break; + } + default: + { + JERRY_UNREACHABLE (); + break; + } + } + } + + /* b. */ + return ECMA_VALUE_TRUE; +} /* ecma_op_general_object_delete */ + +/** + * Property invocation order during [[DefaultValue]] operation with string hint + */ +static const lit_magic_string_id_t to_primitive_string_hint_method_names[2] = { + LIT_MAGIC_STRING_TO_STRING_UL, /**< toString operation */ + LIT_MAGIC_STRING_VALUE_OF_UL, /**< valueOf operation */ +}; + +/** + * Property invocation order during [[DefaultValue]] operation with non string hint + */ +static const lit_magic_string_id_t to_primitive_non_string_hint_method_names[2] = { + LIT_MAGIC_STRING_VALUE_OF_UL, /**< valueOf operation */ + LIT_MAGIC_STRING_TO_STRING_UL, /**< toString operation */ +}; + +/** + * Hints for the ecma general object's toPrimitve operation + */ +static const lit_magic_string_id_t hints[3] = { + LIT_MAGIC_STRING_DEFAULT, /**< "default" hint */ + LIT_MAGIC_STRING_NUMBER, /**< "number" hint */ + LIT_MAGIC_STRING_STRING, /**< "string" hint */ +}; + +/** + * [[DefaultValue]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ + ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + + ecma_value_t obj_value = ecma_make_object_value (obj_p); + + ecma_value_t exotic_to_prim = ecma_op_get_method_by_symbol_id (obj_value, LIT_GLOBAL_SYMBOL_TO_PRIMITIVE); + + if (ECMA_IS_VALUE_ERROR (exotic_to_prim)) + { + return exotic_to_prim; + } + + if (!ecma_is_value_undefined (exotic_to_prim)) + { + ecma_object_t *call_func_p = ecma_get_object_from_value (exotic_to_prim); + ecma_value_t argument = ecma_make_magic_string_value (hints[hint]); + + ecma_value_t result = ecma_op_function_call (call_func_p, obj_value, &argument, 1); + + ecma_free_value (exotic_to_prim); + + if (ECMA_IS_VALUE_ERROR (result) || !ecma_is_value_object (result)) + { + return result; + } + + ecma_free_value (result); + + return ecma_raise_type_error (ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID); + } + + ecma_free_value (exotic_to_prim); + + if (hint == ECMA_PREFERRED_TYPE_NO) + { + hint = ECMA_PREFERRED_TYPE_NUMBER; + } + + return ecma_op_general_object_ordinary_value (obj_p, hint); +} /* ecma_op_general_object_default_value */ + +/** + * Ecma general object's OrdinaryToPrimitive operation + * + * See also: + * ECMA-262 v6 7.1.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, /**< the object */ + ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ +{ + const lit_magic_string_id_t *function_name_ids_p = + (hint == ECMA_PREFERRED_TYPE_STRING ? to_primitive_string_hint_method_names + : to_primitive_non_string_hint_method_names); + + for (uint32_t i = 0; i < 2; i++) + { + ecma_value_t function_value = ecma_op_object_get_by_magic_id (obj_p, function_name_ids_p[i]); + + if (ECMA_IS_VALUE_ERROR (function_value)) + { + return function_value; + } + + ecma_value_t call_completion = ECMA_VALUE_EMPTY; + + if (ecma_op_is_callable (function_value)) + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (function_value); + + call_completion = ecma_op_function_call (func_obj_p, ecma_make_object_value (obj_p), NULL, 0); + } + + ecma_free_value (function_value); + + if (ECMA_IS_VALUE_ERROR (call_completion) + || (!ecma_is_value_empty (call_completion) && !ecma_is_value_object (call_completion))) + { + return call_completion; + } + + ecma_free_value (call_completion); + } + + return ecma_raise_type_error (ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID); +} /* ecma_op_general_object_ordinary_value */ + +/** + * Special types for ecma_op_general_object_define_own_property. + */ +typedef enum +{ + ECMA_OP_OBJECT_DEFINE_GENERIC = 1, /**< generic property */ + ECMA_OP_OBJECT_DEFINE_ACCESSOR = 0, /**< accessor property */ + ECMA_OP_OBJECT_DEFINE_DATA = ECMA_PROPERTY_FLAG_DATA /**< data property */ +} ecma_op_object_define_own_property_type_t; + +/** + * [[DefineOwnProperty]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_define_own_property (object_p, property_name_p, property_desc_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + JERRY_ASSERT (property_name_p != NULL); + + uint8_t property_desc_type = ECMA_OP_OBJECT_DEFINE_GENERIC; + + if (property_desc_p->flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) + { + /* A property descriptor cannot be both named data and named accessor. */ + JERRY_ASSERT ((property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + != (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)); + property_desc_type = ECMA_OP_OBJECT_DEFINE_DATA; + } + else if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + JERRY_ASSERT (!(property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED)); + property_desc_type = ECMA_OP_OBJECT_DEFINE_ACCESSOR; + } + + /* These three asserts ensures that a new property is created with the appropriate default flags. + * E.g. if JERRY_PROP_IS_CONFIGURABLE_DEFINED is false, the newly created property must be non-configurable. */ + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); + + /* 1. */ + ecma_extended_property_ref_t ext_property_ref = { {NULL, }, NULL }; + ecma_property_t current_prop; + + current_prop = ecma_op_object_get_own_property (object_p, + property_name_p, + &ext_property_ref.property_ref, + ECMA_PROPERTY_GET_VALUE | ECMA_PROPERTY_GET_EXT_REFERENCE); + + if (!ECMA_PROPERTY_IS_FOUND (current_prop)) + { + JERRY_ASSERT (current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND + || current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + + /* 3. */ + if (!ecma_op_ordinary_object_is_extensible (object_p)) + { + /* 2. */ + return ECMA_REJECT_WITH_FORMAT (property_desc_p->flags & JERRY_PROP_SHOULD_THROW, + "Cannot define property '%', object is not extensible", + ecma_make_prop_name_value (property_name_p)); + } + + /* 4. */ + uint8_t prop_attributes = (uint8_t) (property_desc_p->flags & ECMA_PROPERTY_FLAGS_MASK); + + if (property_desc_type != ECMA_OP_OBJECT_DEFINE_ACCESSOR) + { + /* a. */ + JERRY_ASSERT (property_desc_type == ECMA_OP_OBJECT_DEFINE_GENERIC + || property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA); + + ecma_property_value_t *new_prop_value_p = + ecma_create_named_data_property (object_p, property_name_p, prop_attributes, NULL); + + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + || ecma_is_value_undefined (property_desc_p->value)); + + new_prop_value_p->value = ecma_copy_value_if_not_object (property_desc_p->value); + } + else + { + /* b. */ + ecma_create_named_accessor_property (object_p, + property_name_p, + property_desc_p->get_p, + property_desc_p->set_p, + prop_attributes, + NULL); + } + + return ECMA_VALUE_TRUE; + } + + /* 6. */ + const bool is_current_configurable = ecma_is_property_configurable (current_prop); + + /* 7. a., b. */ + bool is_enumerable = (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE) != 0; + if (!is_current_configurable + && ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE) + || ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && (is_enumerable != ecma_is_property_enumerable (current_prop))))) + { + if (ECMA_PROPERTY_IS_VIRTUAL (current_prop)) + { + ecma_free_value (ext_property_ref.property_ref.virtual_value); + } + + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + if (ECMA_PROPERTY_IS_VIRTUAL (current_prop)) + { + bool writable_check_failed = (property_desc_p->flags & JERRY_PROP_IS_WRITABLE); + +#if JERRY_MODULE_SYSTEM + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE)) + { + if (JERRY_UNLIKELY (ext_property_ref.property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + if (property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + writable_check_failed = ((property_desc_p->flags ^ current_prop) & JERRY_PROP_IS_WRITABLE) != 0; + } + } + else + { + JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop)); + } +#else /* !JERRY_MODULE_SYSTEM */ + JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop)); +#endif /* JERRY_MODULE_SYSTEM */ + + ecma_value_t result = ECMA_VALUE_TRUE; + + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR || writable_check_failed + || ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + && !ecma_op_same_value (property_desc_p->value, ext_property_ref.property_ref.virtual_value))) + { + result = ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_free_value (ext_property_ref.property_ref.virtual_value); + return result; + } + + /* 8. */ + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_GENERIC) + { + /* No action required. */ + } + else if (JERRY_LIKELY (property_desc_type == (current_prop & ECMA_PROPERTY_FLAG_DATA))) + { + /* If property is configurable, there is no need for checks. */ + if (JERRY_UNLIKELY (!is_current_configurable)) + { + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA) + { + /* 10. a. i. & ii. */ + if (!ecma_is_property_writable (current_prop) + && ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE) + || ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + && !ecma_op_same_value (property_desc_p->value, ext_property_ref.property_ref.value_p->value)))) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + } + else + { + /* 11. */ + + /* a. */ + ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p; + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (value_p); + jmem_cpointer_t prop_desc_getter_cp, prop_desc_setter_cp; + ECMA_SET_POINTER (prop_desc_getter_cp, property_desc_p->get_p); + ECMA_SET_POINTER (prop_desc_setter_cp, property_desc_p->set_p); + + if (((property_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && prop_desc_getter_cp != get_set_pair_p->getter_cp) + || ((property_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + && prop_desc_setter_cp != get_set_pair_p->setter_cp)) + { + /* i., ii. */ + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + } + } + } + else + { + /* 9. */ + if (!is_current_configurable) + { + /* a. */ + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p; + + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR) + { + JERRY_ASSERT (current_prop & ECMA_PROPERTY_FLAG_DATA); + ecma_free_value_if_not_object (value_p->value); + +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); + getter_setter_pair_p->getter_cp = JMEM_CP_NULL; + getter_setter_pair_p->setter_cp = JMEM_CP_NULL; + ECMA_SET_NON_NULL_POINTER (value_p->getter_setter_pair_cp, getter_setter_pair_p); +#else /* !JERRY_CPOINTER_32_BIT */ + value_p->getter_setter_pair.getter_cp = JMEM_CP_NULL; + value_p->getter_setter_pair.setter_cp = JMEM_CP_NULL; +#endif /* JERRY_CPOINTER_32_BIT */ + } + else + { + JERRY_ASSERT (!(current_prop & ECMA_PROPERTY_FLAG_DATA)); +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, value_p->getter_setter_pair_cp); + jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + value_p->value = ECMA_VALUE_UNDEFINED; + } + + /* Update flags */ + ecma_property_t prop_flags = *(ext_property_ref.property_p); + prop_flags = (ecma_property_t) (prop_flags & ~ECMA_PROPERTY_FLAG_WRITABLE); + prop_flags ^= ECMA_PROPERTY_FLAG_DATA; + *(ext_property_ref.property_p) = prop_flags; + } + + /* 12. */ + if (property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (*ext_property_ref.property_p)); + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_named_data_property_assign_value (object_p, ext_property_ref.property_ref.value_p, property_desc_p->value); + } + + if (property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + ecma_set_property_writable_attr (ext_property_ref.property_p, (property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); + } + } + else if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR) + { + JERRY_ASSERT (!(*ext_property_ref.property_p & ECMA_PROPERTY_FLAG_DATA)); + + if (property_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + ecma_set_named_accessor_property_getter (object_p, ext_property_ref.property_ref.value_p, property_desc_p->get_p); + } + + if (property_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + ecma_set_named_accessor_property_setter (object_p, ext_property_ref.property_ref.value_p, property_desc_p->set_p); + } + } + + if (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + { + ecma_set_property_enumerable_attr (ext_property_ref.property_p, + (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); + } + + if (property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + { + ecma_set_property_configurable_attr (ext_property_ref.property_p, + (property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_general_object_define_own_property */ + +/** + * The IsCompatiblePropertyDescriptor method for Proxy object internal methods + * + * See also: + * ECMAScript v6, 9.1.6.2 + * + * @return bool + */ +bool +ecma_op_is_compatible_property_descriptor (const ecma_property_descriptor_t *desc_p, /**< target descriptor */ + const ecma_property_descriptor_t *current_p, /**< current descriptor */ + bool is_extensible) /**< true - if target object is extensible + false - otherwise */ +{ + JERRY_ASSERT (desc_p != NULL); + + /* 2. */ + if (current_p == NULL) + { + return is_extensible; + } + + /* 3. */ + if (desc_p->flags == 0) + { + return true; + } + + /* 4. */ + if ((current_p->flags & desc_p->flags) == desc_p->flags) + { + if ((current_p->flags & JERRY_PROP_IS_VALUE_DEFINED) && ecma_op_same_value (current_p->value, desc_p->value)) + { + return true; + } + + if ((current_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED) && current_p->get_p == desc_p->get_p + && current_p->set_p == desc_p->set_p)) + { + return true; + } + } + + /* 5. */ + if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + if (desc_p->flags & JERRY_PROP_IS_CONFIGURABLE) + { + return false; + } + if ((desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && ((current_p->flags & JERRY_PROP_IS_ENUMERABLE) != (desc_p->flags & JERRY_PROP_IS_ENUMERABLE))) + { + return false; + } + } + + const uint32_t accessor_desc_flags = (JERRY_PROP_IS_SET_DEFINED | JERRY_PROP_IS_GET_DEFINED); + const uint32_t data_desc_flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED); + + bool desc_is_accessor = (desc_p->flags & accessor_desc_flags) != 0; + bool desc_is_data = (desc_p->flags & data_desc_flags) != 0; + bool current_is_data = (current_p->flags & data_desc_flags) != 0; + + /* 6. */ + if (!desc_is_accessor && !desc_is_data) + { + return true; + } + + /* 7. */ + if (current_is_data != desc_is_data) + { + return (current_p->flags & JERRY_PROP_IS_CONFIGURABLE) != 0; + } + + /* 8. */ + if (current_is_data) + { + if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + if (!(current_p->flags & JERRY_PROP_IS_WRITABLE) && (desc_p->flags & JERRY_PROP_IS_WRITABLE)) + { + return false; + } + + if (!(current_p->flags & JERRY_PROP_IS_WRITABLE) && (desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + && !ecma_op_same_value (desc_p->value, current_p->value)) + { + return false; + } + } + + return true; + } + + JERRY_ASSERT ((current_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) != 0); + JERRY_ASSERT ((desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) != 0); + + /* 9. */ + if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + if ((desc_p->flags & JERRY_PROP_IS_SET_DEFINED) && desc_p->set_p != current_p->set_p) + { + return false; + } + + if ((desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && desc_p->get_p != current_p->get_p) + { + return false; + } + } + + return true; +} /* ecma_op_is_compatible_property_descriptor */ + +/** + * CompletePropertyDescriptor method for proxy internal method + * + * See also: + * ECMA-262 v6, 6.2.4.5 + */ +void +ecma_op_to_complete_property_descriptor (ecma_property_descriptor_t *desc_p) /**< target descriptor */ +{ + /* 4. */ + if (!(desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))) + { + /* a. */ + desc_p->flags |= JERRY_PROP_IS_VALUE_DEFINED; + } + /* 5. */ + else + { + desc_p->flags |= (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED); + } +} /* ecma_op_to_complete_property_descriptor */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.h new file mode 100644 index 00000000..210f176c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects-general.h @@ -0,0 +1,50 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_OBJECTS_GENERAL_H +#define ECMA_OBJECTS_GENERAL_H + +#include "ecma-conversion.h" +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +ecma_object_t *ecma_op_create_object_object_noarg (void); +ecma_object_t *ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p); + +ecma_value_t ecma_op_general_object_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_throw); +ecma_value_t ecma_op_general_object_default_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); +ecma_value_t ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); +ecma_value_t ecma_op_general_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); + +void ecma_op_to_complete_property_descriptor (ecma_property_descriptor_t *desc_p); + +bool ecma_op_is_compatible_property_descriptor (const ecma_property_descriptor_t *desc_p, + const ecma_property_descriptor_t *current_p, + bool is_extensible); + +/** + * @} + * @} + */ + +#endif /* !ECMA_OBJECTS_GENERAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.cpp new file mode 100644 index 00000000..b77fb824 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.cpp @@ -0,0 +1,3450 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-objects.h" + +#include "ecma-arguments-object.h" +#include "ecma-array-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lcache.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-proxy-object.h" +#include "ecma-string-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_TYPEDARRAY +#include "ecma-arraybuffer-object.h" +#include "ecma-typedarray-object.h" +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +/** + * Hash bitmap size for ecma objects + */ +#define ECMA_OBJECT_HASH_BITMAP_SIZE 256 + +/** + * Assert that specified object type value is valid + * + * @param type object's implementation-defined type + */ +#ifndef JERRY_NDEBUG +#define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type) JERRY_ASSERT (type < ECMA_OBJECT_TYPE__MAX); +#else /* JERRY_NDEBUG */ +#define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type) +#endif /* !JERRY_NDEBUG */ + +/** + * [[GetOwnProperty]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return pointer to a property - if it exists, + * NULL (i.e. ecma-undefined) - otherwise. + */ +ecma_property_t +ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_ref_t *property_ref_p, /**< property reference */ + uint32_t options) /**< option bits */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); +#if JERRY_BUILTIN_PROXY + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); +#endif /* JERRY_BUILTIN_PROXY */ + JERRY_ASSERT (property_name_p != NULL); + JERRY_ASSERT (options == ECMA_PROPERTY_GET_NO_OPTIONS || property_ref_p != NULL); + + ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); + + switch (base_type) + { + case ECMA_OBJECT_BASE_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + if (ecma_string_is_length (property_name_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + property_ref_p->virtual_value = ecma_make_uint32_value (length); + } + + return ECMA_PROPERTY_VIRTUAL; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); + ecma_string_t *char_str_p = ecma_new_ecma_string_from_code_unit (char_at_idx); + property_ref_p->virtual_value = ecma_make_string_value (char_str_p); + } + + return ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_VIRTUAL; + } + } + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.1 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ecma_prop_name_is_symbol (property_name_p)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + JERRY_ASSERT (index == UINT32_MAX); + + if (!ecma_typedarray_is_element_index (property_name_p)) + { + break; + } + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); + ecma_value_t value = ecma_get_typedarray_element (&info, index); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW; + } + + if (JERRY_UNLIKELY (ecma_is_value_undefined (value))) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; + } + + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = value; + } + else + { + ecma_fast_free_value (value); + } + + return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + if (!ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; + } + + /* ECMA-262 v11, 26.3.1 */ + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); + } + + return ECMA_PROPERTY_VIRTUAL; + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + if (options & ECMA_PROPERTY_GET_EXT_REFERENCE) + { + ((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p; + } + + if (property_ref_p != NULL) + { + property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + } + + return *property_p; + } + + if (options & ECMA_PROPERTY_GET_VALUE) + { + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); + property_ref_p->virtual_value = ecma_fast_copy_value (prop_value_p->value); + } + + return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; + } +#endif /* JERRY_MODULE_SYSTEM */ + } + break; + } + case ECMA_OBJECT_BASE_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_string_is_length (property_name_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = ecma_make_uint32_value (ext_object_p->u.array.length); + } + + uint32_t length_prop = ext_object_p->u.array.length_prop_and_hole_count; + return length_prop & (ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_VIRTUAL); + } + + if (ecma_op_array_is_fast_array (ext_object_p)) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (JERRY_LIKELY (index < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (ecma_is_value_array_hole (values_p[index])) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND; + } + + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = ecma_fast_copy_value (values_p[index]); + } + + return ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; + } + } + + return ECMA_PROPERTY_TYPE_NOT_FOUND; + } + + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + ecma_object_type_t type = ecma_get_object_type (object_p); + + if (property_p == NULL) + { + switch (type) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (object_p)) + { + property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + if (((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS) + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + default: + { + break; + } + } + + if (property_p == NULL) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND; + } + } + else if (type == ECMA_OBJECT_TYPE_CLASS + && ((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS + && (((ecma_extended_object_t *) object_p)->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { +#if JERRY_LCACHE + /* Mapped arguments initialized properties MUST not be lcached */ + if (ecma_is_property_lcached (property_p)) + { + jmem_cpointer_t prop_name_cp; + + if (JERRY_UNLIKELY (ECMA_IS_DIRECT_STRING (property_name_p))) + { + prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (property_name_p); + } + else + { + ECMA_SET_NON_NULL_POINTER (prop_name_cp, property_name_p); + } + ecma_lcache_invalidate (object_p, prop_name_cp, property_p); + } +#endif /* JERRY_LCACHE */ + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + + ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, name_p, true); + + ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), binding_value); + ecma_free_value (binding_value); + } + } + } + + if (options & ECMA_PROPERTY_GET_EXT_REFERENCE) + { + ((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p; + } + + if (property_ref_p != NULL) + { + property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + } + + return *property_p; +} /* ecma_op_object_get_own_property */ + +/** + * Generic [[HasProperty]] operation + * + * See also: + * ECMAScript v6, 9.1.7.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - whether the property is found + */ +ecma_value_t +ecma_op_object_has_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + while (true) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_has (object_p, property_name_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 2 - 3. */ + ecma_property_t property = + ecma_op_object_get_own_property (object_p, property_name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); + + if (property != ECMA_PROPERTY_TYPE_NOT_FOUND) + { +#if JERRY_BUILTIN_TYPEDARRAY + if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP || ECMA_PROPERTY_IS_FOUND (property)); + + return ecma_make_boolean_value (property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + } + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (object_p); + + /* 7. */ + if (proto_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_FALSE; + } + + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + } +} /* ecma_op_object_has_property */ + +/** + * Search the value corresponding to a property name + * + * Note: search includes prototypes + * + * @return ecma value if property is found + * ECMA_VALUE_NOT_FOUND if property is not found + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ + ecma_object_t *object_p, /**< target object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (property_name_p != NULL); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); + + switch (base_type) + { + case ECMA_OBJECT_BASE_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + if (ecma_string_is_length (property_name_p)) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + + return ecma_make_uint32_value (length); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); + return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (char_at_idx)); + } + } + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + + return ecma_op_get_binding_value (lex_env_p, name_p, true); + } + } + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.4 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ecma_prop_name_is_symbol (property_name_p)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + JERRY_ASSERT (index == UINT32_MAX); + + if (!ecma_typedarray_is_element_index (property_name_p)) + { + break; + } + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); + return ecma_get_typedarray_element (&info, index); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + /* ECMA-262 v11, 26.3.1 */ + if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); + } + + return ECMA_VALUE_NOT_FOUND; + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + return ECMA_VALUE_NOT_FOUND; + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); + + if (JERRY_UNLIKELY (prop_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + } + + return ecma_fast_copy_value (prop_value_p->value); + } +#endif /* JERRY_MODULE_SYSTEM */ + } + break; + } + case ECMA_OBJECT_BASE_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_string_is_length (property_name_p)) + { + return ecma_make_uint32_value (ext_object_p->u.array.length); + } + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_LIKELY (index != ECMA_STRING_NOT_ARRAY_INDEX)) + { + if (JERRY_LIKELY (index < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + return (ecma_is_value_array_hole (values_p[index]) ? ECMA_VALUE_NOT_FOUND + : ecma_fast_copy_value (values_p[index])); + } + } + return ECMA_VALUE_NOT_FOUND; + } + + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (object_p)) + { + property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + if (((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS) + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + default: + { + break; + } + } + + if (property_p == NULL) + { + return ECMA_VALUE_NOT_FOUND; + } + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + return ecma_fast_copy_value (prop_value_p->value); + } + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + + return ecma_op_function_call (getter_p, base_value, NULL, 0); +} /* ecma_op_object_find_own */ + +/** + * Search the value corresponding to a property index + * + * Note: this method falls back to the general ecma_op_object_find + * + * @return ecma value if property is found + * ECMA_VALUE_NOT_FOUND if property is not found + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_find_by_index (ecma_object_t *object_p, /**< the object */ + ecma_length_t index) /**< property index */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_find (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index)); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_find (object_p, index_str_p); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_find_by_index */ + +/** + * Search the value corresponding to a property name + * + * Note: search includes prototypes + * + * @return ecma value if property is found + * ECMA_VALUE_NOT_FOUND if property is not found + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_find (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_value_t base_value = ecma_make_object_value (object_p); + + while (true) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_find (object_p, property_name_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t value = ecma_op_object_find_own (base_value, object_p, property_name_p); + + if (ecma_is_value_found (value)) + { + return value; + } + + if (object_p->u2.prototype_cp == JMEM_CP_NULL) + { + break; + } + + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u2.prototype_cp); + } + + return ECMA_VALUE_NOT_FOUND; +} /* ecma_op_object_find */ + +/** + * [[Get]] operation of ecma object + * + * This function returns the value of a named property, or undefined + * if the property is not found in the prototype chain. If the property + * is an accessor, it calls the "get" callback function and returns + * with its result (including error throws). + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + return ecma_op_object_get_with_receiver (object_p, property_name_p, ecma_make_object_value (object_p)); +} /* ecma_op_object_get */ + +/** + * [[Get]] operation of ecma object with the specified receiver + * + * This function returns the value of a named property, or undefined + * if the property is not found in the prototype chain. If the property + * is an accessor, it calls the "get" callback function and returns + * with its result (including error throws). + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_with_receiver (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver to invoke getter function */ +{ + while (true) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_get (object_p, property_name_p, receiver); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t value = ecma_op_object_find_own (receiver, object_p, property_name_p); + + if (ecma_is_value_found (value)) + { + return value; + } + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (object_p); + + if (proto_cp == JMEM_CP_NULL) + { + break; + } + + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_object_get_with_receiver */ + +/** + * [[Get]] operation of ecma object specified for property index + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_by_index (ecma_object_t *object_p, /**< the object */ + ecma_length_t index) /**< property index */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_get (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index)); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_get (object_p, index_str_p); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_get_by_index */ + +/** + * Perform ToLength(O.[[Get]]("length")) operation + * + * The property is converted to uint32 during the operation + * + * @return ECMA_VALUE_ERROR - if there was any error during the operation + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_op_object_get_length (ecma_object_t *object_p, /**< the object */ + ecma_length_t *length_p) /**< [out] length value converted to uint32 */ +{ + if (JERRY_LIKELY (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY)) + { + *length_p = (ecma_length_t) ecma_array_get_length (object_p); + return ECMA_VALUE_EMPTY; + } + + ecma_value_t len_value = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_LENGTH); + ecma_value_t len_number = ecma_op_to_length (len_value, length_p); + ecma_free_value (len_value); + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (len_number) || ecma_is_value_empty (len_number)); + + return len_number; +} /* ecma_op_object_get_length */ + +/** + * [[Get]] operation of ecma object where the property name is a magic string + * + * This function returns the value of a named property, or undefined + * if the property is not found in the prototype chain. If the property + * is an accessor, it calls the "get" callback function and returns + * with its result (including error throws). + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_by_magic_id (ecma_object_t *object_p, /**< the object */ + lit_magic_string_id_t property_id) /**< property magic string id */ +{ + return ecma_op_object_get (object_p, ecma_get_magic_string (property_id)); +} /* ecma_op_object_get_by_magic_id */ + +/** + * Descriptor string for each global symbol + */ +static const uint16_t ecma_global_symbol_descriptions[] = { + LIT_MAGIC_STRING_ASYNC_ITERATOR, LIT_MAGIC_STRING_HAS_INSTANCE, LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, + LIT_MAGIC_STRING_ITERATOR, LIT_MAGIC_STRING_MATCH, LIT_MAGIC_STRING_REPLACE, + LIT_MAGIC_STRING_SEARCH, LIT_MAGIC_STRING_SPECIES, LIT_MAGIC_STRING_SPLIT, + LIT_MAGIC_STRING_TO_PRIMITIVE, LIT_MAGIC_STRING_TO_STRING_TAG, LIT_MAGIC_STRING_UNSCOPABLES, + LIT_MAGIC_STRING_MATCH_ALL, +}; + +JERRY_STATIC_ASSERT ((sizeof (ecma_global_symbol_descriptions) / sizeof (uint16_t) == ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT), + ecma_global_symbol_descriptions_must_have_global_symbol_count_elements); + +/** + * [[Get]] a well-known symbol by the given property id + * + * @return pointer to the requested well-known symbol + */ +ecma_string_t * +ecma_op_get_global_symbol (lit_magic_string_id_t property_id) /**< property symbol id */ +{ + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (property_id)); + + uint32_t symbol_index = (uint32_t) property_id - (uint32_t) LIT_GLOBAL_SYMBOL__FIRST; + jmem_cpointer_t symbol_cp = JERRY_CONTEXT (global_symbols_cp)[symbol_index]; + + if (symbol_cp != JMEM_CP_NULL) + { + ecma_string_t *symbol_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, symbol_cp); + ecma_ref_ecma_string (symbol_p); + return symbol_p; + } + + ecma_string_t *symbol_dot_p = ecma_get_magic_string (LIT_MAGIC_STRING_SYMBOL_DOT_UL); + uint16_t description = ecma_global_symbol_descriptions[symbol_index]; + ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) description); + ecma_string_t *descriptor_p = ecma_concat_ecma_strings (symbol_dot_p, name_p); + + ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (ecma_make_string_value (descriptor_p)); + symbol_p->u.hash = (uint16_t) ((property_id << ECMA_SYMBOL_FLAGS_SHIFT) | ECMA_SYMBOL_FLAG_GLOBAL); + + ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (global_symbols_cp)[symbol_index], symbol_p); + + ecma_ref_ecma_string (symbol_p); + return symbol_p; +} /* ecma_op_get_global_symbol */ + +/** + * Checks whether the string equals to the global symbol. + * + * @return true - if the string equals to the global symbol + * false - otherwise + */ +bool +ecma_op_compare_string_to_global_symbol (ecma_string_t *string_p, /**< string to compare */ + lit_magic_string_id_t property_id) /**< property symbol id */ +{ + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (property_id)); + + uint32_t symbol_index = (uint32_t) property_id - (uint32_t) LIT_GLOBAL_SYMBOL__FIRST; + jmem_cpointer_t symbol_cp = JERRY_CONTEXT (global_symbols_cp)[symbol_index]; + + return (symbol_cp != JMEM_CP_NULL && string_p == ECMA_GET_NON_NULL_POINTER (ecma_string_t, symbol_cp)); +} /* ecma_op_compare_string_to_global_symbol */ + +/** + * [[Get]] operation of ecma object where the property is a well-known symbol + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, /**< the object */ + lit_magic_string_id_t property_id) /**< property symbol id */ +{ + ecma_string_t *symbol_p = ecma_op_get_global_symbol (property_id); + ecma_value_t ret_value = ecma_op_object_get (object_p, symbol_p); + ecma_deref_ecma_string (symbol_p); + + return ret_value; +} /* ecma_op_object_get_by_symbol_id */ + +/** + * GetMethod operation + * + * See also: ECMA-262 v6, 7.3.9 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator function object - if success + * raised error - otherwise + */ +static ecma_value_t +ecma_op_get_method (ecma_value_t value, /**< ecma value */ + ecma_string_t *prop_name_p) /**< property name */ +{ + /* 2. */ + ecma_value_t obj_value = ecma_op_to_object (value); + + if (ECMA_IS_VALUE_ERROR (obj_value)) + { + return obj_value; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); + ecma_value_t func; + + func = ecma_op_object_get (obj_p, prop_name_p); + ecma_deref_object (obj_p); + + /* 3. */ + if (ECMA_IS_VALUE_ERROR (func)) + { + return func; + } + + /* 4. */ + if (ecma_is_value_undefined (func) || ecma_is_value_null (func)) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 5. */ + if (!ecma_op_is_callable (func)) + { + ecma_free_value (func); + return ecma_raise_type_error (ECMA_ERR_ITERATOR_IS_NOT_CALLABLE); + } + + /* 6. */ + return func; +} /* ecma_op_get_method */ + +/** + * GetMethod operation when the property is a well-known symbol + * + * See also: ECMA-262 v6, 7.3.9 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator function object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_get_method_by_symbol_id (ecma_value_t value, /**< ecma value */ + lit_magic_string_id_t symbol_id) /**< property symbol id */ +{ + ecma_string_t *prop_name_p = ecma_op_get_global_symbol (symbol_id); + ecma_value_t ret_value = ecma_op_get_method (value, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + + return ret_value; +} /* ecma_op_get_method_by_symbol_id */ + +/** + * GetMethod operation when the property is a magic string + * + * See also: ECMA-262 v6, 7.3.9 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator function object - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_get_method_by_magic_id (ecma_value_t value, /**< ecma value */ + lit_magic_string_id_t magic_id) /**< property magic id */ +{ + return ecma_op_get_method (value, ecma_get_magic_string (magic_id)); +} /* ecma_op_get_method_by_magic_id */ + +/** + * [[Put]] ecma general object's operation specialized for property index + * + * Note: This function falls back to the general ecma_op_object_put + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_object_put_by_index (ecma_object_t *object_p, /**< the object */ + ecma_length_t index, /**< property index */ + ecma_value_t value, /**< ecma value */ + bool is_throw) /**< flag that controls failure handling */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_put (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), value, is_throw); + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_put (object_p, index_str_p, value, is_throw); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_put_by_index */ + +/** + * [[Put]] ecma general object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.5 + * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + * + * Returns with ECMA_VALUE_TRUE if the operation is + * successful. Otherwise it returns with an error object + * or ECMA_VALUE_FALSE. + * + * Note: even if is_throw is false, the setter can throw an + * error, and this function returns with that error. + */ +ecma_value_t +ecma_op_object_put (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + bool is_throw) /**< flag that controls failure handling */ +{ + return ecma_op_object_put_with_receiver (object_p, + property_name_p, + value, + ecma_make_object_value (object_p), + is_throw); +} /* ecma_op_object_put */ + +/** + * [[Set]] ( P, V, Receiver) operation part for ordinary objects + * + * See also: ECMAScript v6, 9.19.9 + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< value to set */ + bool is_throw) /**< flag that controls failure handling */ +{ + /* 5.b */ + if (!ecma_is_value_object (receiver)) + { + return ECMA_REJECT (is_throw, ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT); + } + + ecma_object_t *receiver_obj_p = ecma_get_object_from_value (receiver); + + ecma_property_descriptor_t prop_desc; + /* 5.c */ + ecma_value_t status = ecma_op_object_get_own_property_descriptor (receiver_obj_p, property_name_p, &prop_desc); + + /* 5.d */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + /* 5.e */ + if (ecma_is_value_true (status)) + { + ecma_value_t result; + + /* 5.e.i - 5.e.ii */ + if (prop_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED) + || !(prop_desc.flags & JERRY_PROP_IS_WRITABLE)) + { + result = ecma_raise_property_redefinition (property_name_p, prop_desc.flags); + } + else + { + /* 5.e.iii */ + JERRY_ASSERT (prop_desc.flags & JERRY_PROP_IS_VALUE_DEFINED); + ecma_free_value (prop_desc.value); + prop_desc.value = ecma_copy_value (value); + + /* 5.e.iv */ + result = ecma_op_object_define_own_property (receiver_obj_p, property_name_p, &prop_desc); + + if (JERRY_UNLIKELY (ecma_is_value_false (result))) + { + result = ECMA_REJECT (is_throw, ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); + } + } + + ecma_free_property_descriptor (&prop_desc); + + return result; + } + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (receiver_obj_p)) + { + ecma_property_descriptor_t desc; + /* Based on: ES6 9.1.9 [[Set]] 4.d.i. / ES11 9.1.9.2 OrdinarySetWithOwnDescriptor 2.c.i. */ + desc.flags = (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE + | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED + | JERRY_PROP_IS_VALUE_DEFINED); + desc.value = value; + ecma_value_t ret_value = ecma_proxy_object_define_own_property (receiver_obj_p, property_name_p, &desc); + + if (JERRY_UNLIKELY (ecma_is_value_false (ret_value))) + { + ret_value = ECMA_REJECT (is_throw, ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); + } + + return ret_value; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (receiver_obj_p))) + { + ecma_fast_array_convert_to_normal (receiver_obj_p); + } + + /* 5.f.i */ + ecma_property_value_t *new_prop_value_p; + new_prop_value_p = ecma_create_named_data_property (receiver_obj_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value)); + new_prop_value_p->value = ecma_copy_value_if_not_object (value); + + return ECMA_VALUE_TRUE; +} /* ecma_op_object_put_apply_receiver */ + +/** + * [[Put]] ecma general object's operation with given receiver + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.5 + * ECMA-262 v6, 9.1.9 + * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 + * + * @return ecma value + * The returned value must be freed with ecma_free_value. + * + * Returns with ECMA_VALUE_TRUE if the operation is + * successful. Otherwise it returns with an error object + * or ECMA_VALUE_FALSE. + * + * Note: even if is_throw is false, the setter can throw an + * error, and this function returns with that error. + */ +ecma_value_t +ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (property_name_p != NULL); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_set (object_p, property_name_p, value, receiver, is_throw); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); + + switch (base_type) + { + case ECMA_OBJECT_BASE_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { + ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); + ecma_op_set_mutable_binding (lex_env_p, name_p, value, true); + return ECMA_VALUE_TRUE; + } + } + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.5 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + if (ecma_prop_name_is_symbol (property_name_p)) + { + break; + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + JERRY_ASSERT (index == UINT32_MAX); + + if (!ecma_typedarray_is_element_index (property_name_p)) + { + break; + } + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); + return ecma_set_typedarray_element (&info, value, index); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } +#endif /* JERRY_MODULE_SYSTEM */ + } + break; + } + case ECMA_OBJECT_BASE_TYPE_ARRAY: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_string_is_length (property_name_p)) + { + if (ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_op_array_object_set_length (object_p, value, 0); + } + + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) + { + ecma_fast_array_convert_to_normal (object_p); + } + else if (ecma_fast_array_set_property (object_p, index, value)) + { + return ECMA_VALUE_TRUE; + } + } + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { + switch (ecma_get_object_type (object_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (object_p)) + { + property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + } + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + if (ecma_string_is_length (property_name_p)) + { + /* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */ + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp)) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + } + + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + default: + { + break; + } + } + } + + jmem_cpointer_t setter_cp = JMEM_CP_NULL; + + if (property_p != NULL) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + if (ecma_is_property_writable (*property_p)) + { + if (ecma_make_object_value (object_p) != receiver) + { + return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); + } + + /* There is no need for special casing arrays here because changing the + * value of an existing property never changes the length of an array. */ + ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + return ECMA_VALUE_TRUE; + } + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p; + get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (property_p)); + setter_cp = get_set_pair_p->setter_cp; + } + } + else + { + bool create_new_property = true; + + jmem_cpointer_t obj_cp; + ECMA_SET_NON_NULL_POINTER (obj_cp, object_p); + ecma_object_t *proto_p = object_p; + + while (true) + { + obj_cp = ecma_op_ordinary_object_get_prototype_of (proto_p); + + if (obj_cp == JMEM_CP_NULL) + { + break; + } + + ecma_property_ref_t property_ref = { NULL }; + proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_cp); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (proto_p)) + { + return ecma_op_object_put_with_receiver (proto_p, property_name_p, value, receiver, is_throw); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_t inherited_property = + ecma_op_object_get_own_property (proto_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_NO_OPTIONS); + + if (ECMA_PROPERTY_IS_FOUND (inherited_property)) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (inherited_property)); + + if (!(inherited_property & ECMA_PROPERTY_FLAG_DATA)) + { + setter_cp = ecma_get_named_accessor_property (property_ref.value_p)->setter_cp; + create_new_property = false; + break; + } + + create_new_property = ecma_is_property_writable (inherited_property); + break; + } + + JERRY_ASSERT (inherited_property == ECMA_PROPERTY_TYPE_NOT_FOUND + || inherited_property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + } + +#if JERRY_BUILTIN_PROXY + if (create_new_property && ecma_is_value_object (receiver) + && ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (receiver))) + { + return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (create_new_property && ecma_op_ordinary_object_is_extensible (object_p)) + { + const ecma_object_base_type_t obj_base_type = ecma_get_object_base_type (object_p); + + if (obj_base_type == ECMA_OBJECT_BASE_TYPE_CLASS) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS + && ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; + return ecma_builtin_helper_def_prop (object_p, property_name_p, value, flags); + } + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (obj_base_type == ECMA_OBJECT_BASE_TYPE_ARRAY && index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (index < UINT32_MAX && index >= ext_object_p->u.array.length) + { + if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + ext_object_p->u.array.length = index + 1; + } + } + + return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); + + ecma_property_value_t *new_prop_value_p; + new_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value)); + new_prop_value_p->value = ecma_copy_value_if_not_object (value); + return ECMA_VALUE_TRUE; + } + } + + if (setter_cp == JMEM_CP_NULL) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + ecma_value_t ret_value = + ecma_op_function_call (ECMA_GET_NON_NULL_POINTER (ecma_object_t, setter_cp), receiver, &value, 1); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_fast_free_value (ret_value); + ret_value = ECMA_VALUE_TRUE; + } + + return ret_value; +} /* ecma_op_object_put_with_receiver */ + +/** + * [[Delete]] ecma object's operation specialized for property index + * + * Note: + * This method falls back to the general ecma_op_object_delete + * + * @return true - if deleted successfully + * false - or type error otherwise (based in 'is_throw') + */ +ecma_value_t +ecma_op_object_delete_by_index (ecma_object_t *obj_p, /**< the object */ + ecma_length_t index, /**< property index */ + bool is_throw) /**< flag that controls failure handling */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_delete (obj_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), is_throw); + ; + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_op_object_delete (obj_p, index_str_p, is_throw); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_delete_by_index */ + +/** + * [[Delete]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * Note: + * returned value must be freed with ecma_free_value + * + * @return true - if deleted successfully + * false - or type error otherwise (based in 'is_throw') + */ +ecma_value_t +ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_strict) /**< flag that controls failure handling */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (property_name_p != NULL); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_delete_property (obj_p, property_name_p, is_strict); + } +#endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); + + return ecma_op_general_object_delete (obj_p, property_name_p, is_strict); +} /* ecma_op_object_delete */ + +/** + * [[DefaultValue]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_default_value (ecma_object_t *obj_p, /**< the object */ + ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); + + /* + * typedef ecma_property_t * (*default_value_ptr_t) (ecma_object_t *, ecma_string_t *); + * static const default_value_ptr_t default_value [ECMA_OBJECT_TYPE__COUNT] = + * { + * [ECMA_OBJECT_TYPE_GENERAL] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_CLASS] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_NATIVE_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_ARRAY] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_BOUND_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_PSEUDO_ARRAY] = &ecma_op_general_object_default_value + * }; + * + * return default_value[type] (obj_p, property_name_p); + */ + + return ecma_op_general_object_default_value (obj_p, hint); +} /* ecma_op_object_default_value */ + +/** + * [[DefineOwnProperty]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (property_name_p != NULL); + + const ecma_object_type_t type = ecma_get_object_type (obj_p); + + switch (type) + { + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + return ecma_op_arguments_object_define_own_property (obj_p, property_name_p, property_desc_p); + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.1 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + return ecma_op_typedarray_define_own_property (obj_p, property_name_p, property_desc_p); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } + break; + } + case ECMA_OBJECT_TYPE_ARRAY: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + return ecma_op_array_object_define_own_property (obj_p, property_name_p, property_desc_p); + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + return ecma_proxy_object_define_own_property (obj_p, property_name_p, property_desc_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + default: + { + break; + } + } + + return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); +} /* ecma_op_object_define_own_property */ + +/** + * Get property descriptor from specified property + * + * depending on the property type the following fields are set: + * - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] }; + * - for named accessor properties: { [Get] - if defined, + * [Set] - if defined, + * [Enumerable], [Configurable] + * }. + * + * The output property descriptor will always be initialized to an empty descriptor. + * + * @return ECMA_VALUE_ERROR - if the Proxy.[[GetOwnProperty]] operation raises error + * ECMA_VALUE_{TRUE, FALSE} - if property found or not + */ +ecma_value_t +ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + *prop_desc_p = ecma_make_empty_property_descriptor (); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + return ecma_proxy_object_get_own_property_descriptor (object_p, property_name_p, prop_desc_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_ref_t property_ref; + property_ref.virtual_value = ECMA_VALUE_EMPTY; + ecma_property_t property = + ecma_op_object_get_own_property (object_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_VALUE); + + if (!ECMA_PROPERTY_IS_FOUND (property)) + { +#if JERRY_BUILTIN_TYPEDARRAY + if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + + return ECMA_VALUE_FALSE; + } + + uint32_t flags = ecma_is_property_enumerable (property) ? JERRY_PROP_IS_ENUMERABLE : JERRY_PROP_NO_OPTS; + flags |= ecma_is_property_configurable (property) ? JERRY_PROP_IS_CONFIGURABLE : JERRY_PROP_NO_OPTS; + + prop_desc_p->flags = (uint16_t) (JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | flags); + + if (property & ECMA_PROPERTY_FLAG_DATA) + { + if (!ECMA_PROPERTY_IS_VIRTUAL (property)) + { + prop_desc_p->value = ecma_copy_value (property_ref.value_p->value); + } + else + { +#if JERRY_MODULE_SYSTEM + if (JERRY_UNLIKELY (property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } +#endif /* JERRY_MODULE_SYSTEM */ + prop_desc_p->value = property_ref.virtual_value; + } + + prop_desc_p->flags |= + (uint16_t) (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED + | (ecma_is_property_writable (property) ? JERRY_PROP_IS_WRITABLE : JERRY_PROP_NO_OPTS)); + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (property_ref.value_p); + prop_desc_p->flags |= (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + prop_desc_p->get_p = NULL; + } + else + { + prop_desc_p->get_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + ecma_ref_object (prop_desc_p->get_p); + } + + if (get_set_pair_p->setter_cp == JMEM_CP_NULL) + { + prop_desc_p->set_p = NULL; + } + else + { + prop_desc_p->set_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp); + ecma_ref_object (prop_desc_p->set_p); + } + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_object_get_own_property_descriptor */ + +#if JERRY_BUILTIN_PROXY +/** + * Get property descriptor from a target value for a specified property. + * + * For more details see ecma_op_object_get_own_property_descriptor + * + * @return ECMA_VALUE_ERROR - if the Proxy.[[GetOwnProperty]] operation raises error + * ECMA_VALUE_{TRUE, FALSE} - if property found or not + */ +ecma_value_t +ecma_op_get_own_property_descriptor (ecma_value_t target, /**< target value */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (!ecma_is_value_object (target)) + { + return ECMA_VALUE_FALSE; + } + + return ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (target), property_name_p, prop_desc_p); +} /* ecma_op_get_own_property_descriptor */ +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * [[HasInstance]] ecma object's operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 9 + * + * @return ecma value containing a boolean value or an error + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_has_instance (ecma_object_t *obj_p, /**< the object */ + ecma_value_t value) /**< argument 'V' */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); + + if (ecma_op_object_is_callable (obj_p)) + { + return ecma_op_function_has_instance (obj_p, value); + } + + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT); +} /* ecma_op_object_has_instance */ + +/** + * General [[GetPrototypeOf]] abstract operation + * + * Note: returned valid object must be freed. + * + * @return ecma_object_t * - prototype of the input object. + * ECMA_OBJECT_POINTER_ERROR - error reported during Proxy resolve. + * NULL - the input object does not have a prototype. + */ +ecma_object_t * +ecma_op_object_get_prototype_of (ecma_object_t *obj_p) /**< input object */ +{ + JERRY_ASSERT (obj_p != NULL); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + ecma_value_t proto = ecma_proxy_object_get_prototype_of (obj_p); + + if (ECMA_IS_VALUE_ERROR (proto)) + { + return ECMA_OBJECT_POINTER_ERROR; + } + if (ecma_is_value_null (proto)) + { + return NULL; + } + + JERRY_ASSERT (ecma_is_value_object (proto)); + + return ecma_get_object_from_value (proto); + } + else +#endif /* JERRY_BUILTIN_PROXY */ + { + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (obj_p); + + if (proto_cp == JMEM_CP_NULL) + { + return NULL; + } + + ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (proto_p); + + return proto_p; + } +} /* ecma_op_object_get_prototype_of */ + +/** + * Object's isPrototypeOf operation + * + * See also: + * ECMA-262 v5, 15.2.4.6; 3 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the target object is prototype of the base object + * ECMA_VALUE_FALSE - if the target object is not prototype of the base object + */ +ecma_value_t +ecma_op_object_is_prototype_of (ecma_object_t *base_p, /**< base object */ + ecma_object_t *target_p) /**< target object */ +{ + ecma_ref_object (target_p); + + do + { + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (target_p); + ecma_deref_object (target_p); + + if (proto_p == NULL) + { + return ECMA_VALUE_FALSE; + } + else if (proto_p == ECMA_OBJECT_POINTER_ERROR) + { + return ECMA_VALUE_ERROR; + } + else if (proto_p == base_p) + { + ecma_deref_object (proto_p); + return ECMA_VALUE_TRUE; + } + + /* Advance up on prototype chain. */ + target_p = proto_p; + } while (true); +} /* ecma_op_object_is_prototype_of */ + +/** + * Object's EnumerableOwnPropertyNames operation + * + * See also: + * ECMA-262 v11, 7.3.23 + * + * @return NULL - if operation fails + * collection of property names / values / name-value pairs - otherwise + */ +ecma_collection_t * +ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_enumerable_property_names_options_t option) /**< listing option */ +{ + /* 2. */ + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); + +#if JERRY_BUILTIN_PROXY + if (JERRY_UNLIKELY (prop_names_p == NULL)) + { + return prop_names_p; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t *names_buffer_p = prop_names_p->buffer_p; + /* 3. */ + ecma_collection_t *properties_p = ecma_new_collection (); + + /* 4. */ + for (uint32_t i = 0; i < prop_names_p->item_count; i++) + { + /* 4.a */ + if (ecma_is_value_string (names_buffer_p[i])) + { + ecma_string_t *key_p = ecma_get_string_from_value (names_buffer_p[i]); + + /* 4.a.i */ + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, key_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (prop_names_p); + ecma_collection_free (properties_p); + + return NULL; + } + + const bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) != 0; + ecma_free_property_descriptor (&prop_desc); + /* 4.a.ii */ + if (is_enumerable) + { + /* 4.a.ii.1 */ + if (option == ECMA_ENUMERABLE_PROPERTY_KEYS) + { + ecma_collection_push_back (properties_p, ecma_copy_value (names_buffer_p[i])); + } + else + { + /* 4.a.ii.2.a */ + ecma_value_t value = ecma_op_object_get (obj_p, key_p); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ecma_collection_free (prop_names_p); + ecma_collection_free (properties_p); + + return NULL; + } + + /* 4.a.ii.2.b */ + if (option == ECMA_ENUMERABLE_PROPERTY_VALUES) + { + ecma_collection_push_back (properties_p, value); + } + else + { + /* 4.a.ii.2.c.i */ + JERRY_ASSERT (option == ECMA_ENUMERABLE_PROPERTY_ENTRIES); + + /* 4.a.ii.2.c.ii */ + ecma_object_t *entry_p = ecma_op_new_array_object (2); + + ecma_builtin_helper_def_prop_by_index (entry_p, + 0, + names_buffer_p[i], + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_builtin_helper_def_prop_by_index (entry_p, 1, value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_free_value (value); + + /* 4.a.ii.2.c.iii */ + ecma_collection_push_back (properties_p, ecma_make_object_value (entry_p)); + } + } + } + } + } + + ecma_collection_free (prop_names_p); + + return properties_p; +} /* ecma_op_object_get_enumerable_property_names */ + +/** + * Helper method for getting lazy instantiated properties for [[OwnPropertyKeys]] + */ +static void +ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + switch (ecma_get_object_type (obj_p)) + { + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + if (ecma_builtin_function_is_routine (obj_p)) + { + ecma_builtin_routine_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + /* FALLTHRU */ + } + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ecma_builtin_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + switch (ext_object_p->u.cls.type) + { + case ECMA_OBJECT_CLASS_STRING: + { + ecma_op_string_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_CLASS_ARGUMENTS: + { + ecma_op_arguments_object_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } +#if JERRY_BUILTIN_TYPEDARRAY + /* ES2015 9.4.5.1 */ + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + ecma_op_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ecma_op_external_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_op_bound_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); + break; + } + case ECMA_OBJECT_TYPE_ARRAY: + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + break; + } + default: + { + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_GENERAL + || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + break; + } + } +} /* ecma_object_list_lazy_property_names */ + +/** + * Helper routine for heapsort algorithm. + */ +static void +ecma_op_object_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */ + uint32_t item_count, /**< number of items */ + uint32_t item_index) /**< index of updated item */ +{ + while (true) + { + uint32_t highest_index = item_index; + uint32_t current_index = (item_index << 1) + 1; + + if (current_index >= item_count) + { + return; + } + + uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[highest_index])); + uint32_t left_value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index])); + + if (value < left_value) + { + highest_index = current_index; + value = left_value; + } + + current_index++; + + if (current_index < item_count + && value < ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index]))) + { + highest_index = current_index; + } + + if (highest_index == item_index) + { + return; + } + + ecma_value_t tmp = buffer_p[highest_index]; + buffer_p[highest_index] = buffer_p[item_index]; + buffer_p[item_index] = tmp; + + item_index = highest_index; + } +} /* ecma_op_object_heap_sort_shift_down */ + +/** + * Object's [[OwnPropertyKeys]] internal method + * + * Order of names in the collection: + * - integer indices in ascending order + * - other indices in creation order (for built-ins: the order of the properties are listed in specification). + * + * Note: + * Implementation of the routine assumes that new properties are appended to beginning of corresponding object's + * property list, and the list is not reordered (in other words, properties are stored in order that is reversed + * to the properties' addition order). + * + * @return NULL - if the Proxy.[[OwnPropertyKeys]] operation raises error + * collection of property names - otherwise + */ +ecma_collection_t * +ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */ + jerry_property_filter_t filter) /**< name filters */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_own_property_keys (obj_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_op_object_is_fast_array (obj_p)) + { + return ecma_fast_array_object_own_property_keys (obj_p, filter); + } + + ecma_collection_t *prop_names_p = ecma_new_collection (); + ecma_property_counter_t prop_counter = { 0, 0, 0 }; + + ecma_object_list_lazy_property_names (obj_p, prop_names_p, &prop_counter, filter); + + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + jmem_cpointer_t counter_prop_iter_cp = prop_iter_cp; + + uint32_t array_index_named_props = 0; + uint32_t string_named_props = 0; + uint32_t symbol_named_props = 0; + + while (counter_prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, counter_prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_property_t *property_p = prop_iter_p->types + i; + + if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + { + continue; + } + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); + + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + array_index_named_props++; + } + else if (ecma_prop_name_is_symbol (name_p)) + { + if (!(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) + { + symbol_named_props++; + } + } + else + { + string_named_props++; + } + + ecma_deref_ecma_string (name_p); + } + + counter_prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + { + JERRY_ASSERT (prop_counter.array_index_named_props == 0); + array_index_named_props = 0; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + JERRY_ASSERT (prop_counter.string_named_props == 0); + string_named_props = 0; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) + { + JERRY_ASSERT (prop_counter.symbol_named_props == 0); + symbol_named_props = 0; + } + + uint32_t total = array_index_named_props + string_named_props + symbol_named_props; + + if (total == 0) + { + return prop_names_p; + } + + ecma_collection_reserve (prop_names_p, total); + prop_names_p->item_count += total; + + ecma_value_t *buffer_p = prop_names_p->buffer_p; + ecma_value_t *array_index_current_p = buffer_p + array_index_named_props + prop_counter.array_index_named_props; + ecma_value_t *string_current_p = array_index_current_p + string_named_props + prop_counter.string_named_props; + + ecma_value_t *symbol_current_p = string_current_p + symbol_named_props + prop_counter.symbol_named_props; + + if (prop_counter.symbol_named_props > 0 && (array_index_named_props + string_named_props) > 0) + { + memmove ((void *) string_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props + prop_counter.string_named_props), + prop_counter.symbol_named_props * sizeof (ecma_value_t)); + } + + if (prop_counter.string_named_props > 0 && array_index_named_props > 0) + { + memmove ((void *) array_index_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props), + prop_counter.string_named_props * sizeof (ecma_value_t)); + } + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_property_t *property_p = prop_iter_p->types + i; + + if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + { + continue; + } + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); + + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + *(--array_index_current_p) = ecma_make_string_value (name_p); + continue; + } + } + else if (ecma_prop_name_is_symbol (name_p)) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) && !(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) + { + *(--symbol_current_p) = ecma_make_symbol_value (name_p); + continue; + } + } + else + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + *(--string_current_p) = ecma_make_string_value (name_p); + continue; + } + } + + ecma_deref_ecma_string (name_p); + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (array_index_named_props > 1 || (array_index_named_props == 1 && prop_counter.array_index_named_props > 0)) + { + uint32_t prev_value = 0; + ecma_value_t *array_index_p = buffer_p + prop_counter.array_index_named_props; + ecma_value_t *array_index_end_p = array_index_p + array_index_named_props; + + if (prop_counter.array_index_named_props > 0) + { + prev_value = ecma_string_get_array_index (ecma_get_string_from_value (array_index_p[-1])); + } + + do + { + uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (*array_index_p++)); + + if (value < prev_value) + { + uint32_t array_props = prop_counter.array_index_named_props + array_index_named_props; + uint32_t i = (array_props >> 1) - 1; + + do + { + ecma_op_object_heap_sort_shift_down (buffer_p, array_props, i); + } while (i-- > 0); + + i = array_props - 1; + + do + { + ecma_value_t tmp = buffer_p[i]; + buffer_p[i] = buffer_p[0]; + buffer_p[0] = tmp; + + ecma_op_object_heap_sort_shift_down (buffer_p, i, 0); + } while (--i > 0); + + break; + } + + prev_value = value; + } while (array_index_p < array_index_end_p); + } + + return prop_names_p; +} /* ecma_op_object_own_property_keys */ + +/** + * EnumerateObjectProperties abstract method + * + * See also: + * ECMA-262 v11, 13.7.5.15 + * + * @return NULL - if the Proxy.[[OwnPropertyKeys]] operation raises error + * collection of enumerable property names - otherwise + */ +ecma_collection_t * +ecma_op_object_enumerate (ecma_object_t *obj_p) /**< object */ +{ + ecma_collection_t *visited_names_p = ecma_new_collection (); + ecma_collection_t *return_names_p = ecma_new_collection (); + + ecma_ref_object (obj_p); + + while (true) + { + ecma_collection_t *keys = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); + + if (JERRY_UNLIKELY (keys == NULL)) + { + ecma_collection_free (return_names_p); + ecma_collection_free (visited_names_p); + ecma_deref_object (obj_p); + return keys; + } + + for (uint32_t i = 0; i < keys->item_count; i++) + { + ecma_value_t prop_name = keys->buffer_p[i]; + ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name); + + if (ecma_prop_name_is_symbol (name_p)) + { + continue; + } + + ecma_property_descriptor_t prop_desc; + ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, name_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (get_desc)) + { + ecma_collection_free (keys); + ecma_collection_free (return_names_p); + ecma_collection_free (visited_names_p); + ecma_deref_object (obj_p); + return NULL; + } + + if (ecma_is_value_true (get_desc)) + { + bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) != 0; + ecma_free_property_descriptor (&prop_desc); + + if (ecma_collection_has_string_value (visited_names_p, name_p) + || ecma_collection_has_string_value (return_names_p, name_p)) + { + continue; + } + + ecma_ref_ecma_string (name_p); + + if (is_enumerable) + { + ecma_collection_push_back (return_names_p, prop_name); + } + else + { + ecma_collection_push_back (visited_names_p, prop_name); + } + } + } + + ecma_collection_free (keys); + + /* Query the prototype. */ + ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_p); + ecma_deref_object (obj_p); + + if (proto_p == NULL) + { + break; + } + else if (JERRY_UNLIKELY (proto_p == ECMA_OBJECT_POINTER_ERROR)) + { + ecma_collection_free (return_names_p); + ecma_collection_free (visited_names_p); + return NULL; + } + + /* Advance up on prototype chain. */ + obj_p = proto_p; + } + + ecma_collection_free (visited_names_p); + + return return_names_p; +} /* ecma_op_object_enumerate */ + +#ifndef JERRY_NDEBUG + +/** + * Check if passed object is the instance of specified built-in. + * + * @return true - if the object is instance of the specified built-in + * false - otherwise + */ +static bool +ecma_builtin_is (ecma_object_t *object_p, /**< pointer to an object */ + ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + + ecma_object_type_t type = ecma_get_object_type (object_p); + + switch (type) + { + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + { + ecma_extended_object_t *built_in_object_p = (ecma_extended_object_t *) object_p; + + return (built_in_object_p->u.built_in.id == builtin_id && built_in_object_p->u.built_in.routine_id == 0); + } + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + ecma_extended_built_in_object_t *extended_built_in_object_p = (ecma_extended_built_in_object_t *) object_p; + + return (extended_built_in_object_p->built_in.id == builtin_id + && extended_built_in_object_p->built_in.routine_id == 0); + } + default: + { + return false; + } + } +} /* ecma_builtin_is */ + +#endif /* !JERRY_NDEBUG */ + +/** + * The function is used in the assert of ecma_object_get_class_name + * + * @return true - if class name is an object + * false - otherwise + */ +static inline bool +ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */ +{ +#ifndef JERRY_NDEBUG + return (ecma_builtin_is_global (obj_p) +#if JERRY_BUILTIN_TYPEDARRAY + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE) +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE) +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_TYPEDARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT8ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT16ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT16ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_INT32ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT32ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_FLOAT32ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY_PROTOTYPE) +#if JERRY_NUMBER_TYPE_FLOAT64 + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_FLOAT64ARRAY_PROTOTYPE) +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_BIGINT_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_BIGINT64ARRAY_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_BIGUINT64ARRAY_PROTOTYPE) +#endif /* JERRY_BUILTIN_BIGINT */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REGEXP_STRING_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_AGGREGATE_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ERROR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATE_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ASYNC_FUNCTION_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE) +#if JERRY_BUILTIN_CONTAINER + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_MAP_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SET_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_WEAKMAP_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SET_ITERATOR_PROTOTYPE) +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_WEAKREF + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_WEAKREF_PROTOTYPE) +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_DATAVIEW + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE) +#endif /* JERRY_BUILTIN_DATAVIEW */ + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE)); +#else /* JERRY_NDEBUG */ + JERRY_UNUSED (obj_p); + return true; +#endif /* !JERRY_NDEBUG */ +} /* ecma_object_check_class_name_is_object */ + +/** + * Used by ecma_object_get_class_name to get the magic string id of class objects + */ +static const uint16_t ecma_class_object_magic_string_id[] = { + /* These objects require custom property resolving. */ + LIT_MAGIC_STRING_STRING_UL, /**< magic string id of ECMA_OBJECT_CLASS_STRING */ + LIT_MAGIC_STRING_ARGUMENTS_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARGUMENTS */ +#if JERRY_BUILTIN_TYPEDARRAY + LIT_MAGIC_STRING__EMPTY, /**< ECMA_OBJECT_CLASS_TYPEDARRAY needs special resolver */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + LIT_MAGIC_STRING_MODULE_UL, /**< magic string id of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* These objects are marked by Garbage Collector. */ + LIT_MAGIC_STRING_GENERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_GENERATOR */ + LIT_MAGIC_STRING_ASYNC_GENERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_ASYNC_GENERATOR */ + LIT_MAGIC_STRING_ARRAY_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARRAY_ITERATOR */ + LIT_MAGIC_STRING_SET_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_SET_ITERATOR */ + LIT_MAGIC_STRING_MAP_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_MAP_ITERATOR */ +#if JERRY_BUILTIN_REGEXP + LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_REGEXP_STRING_ITERATOR */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_MODULE_SYSTEM + LIT_MAGIC_STRING_MODULE_UL, /**< magic string id of ECMA_OBJECT_CLASS_MODULE */ +#endif /* JERRY_MODULE_SYSTEM */ + LIT_MAGIC_STRING_PROMISE_UL, /**< magic string id of ECMA_OBJECT_CLASS_PROMISE */ + LIT_MAGIC_STRING_OBJECT_UL, /**< magic string id of ECMA_OBJECT_CLASS_PROMISE_CAPABILITY */ + LIT_MAGIC_STRING_OBJECT_UL, /**< magic string id of ECMA_OBJECT_CLASS_ASYNC_FROM_SYNC_ITERATOR */ +#if JERRY_BUILTIN_DATAVIEW + LIT_MAGIC_STRING_DATAVIEW_UL, /**< magic string id of ECMA_OBJECT_CLASS_DATAVIEW */ +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_CONTAINER + LIT_MAGIC_STRING__EMPTY, /**< magic string id of ECMA_OBJECT_CLASS_CONTAINER needs special resolver */ +#endif /* JERRY_BUILTIN_CONTAINER */ + + /* Normal objects. */ + LIT_MAGIC_STRING_BOOLEAN_UL, /**< magic string id of ECMA_OBJECT_CLASS_BOOLEAN */ + LIT_MAGIC_STRING_NUMBER_UL, /**< magic string id of ECMA_OBJECT_CLASS_NUMBER */ + LIT_MAGIC_STRING_ERROR_UL, /**< magic string id of ECMA_OBJECT_CLASS_ERROR */ + LIT_MAGIC_STRING_OBJECT_UL, /**< magic string id of ECMA_OBJECT_CLASS_INTERNAL_OBJECT */ +#if JERRY_PARSER + LIT_MAGIC_STRING_SCRIPT_UL, /**< magic string id of ECMA_OBJECT_CLASS_SCRIPT */ +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_DATE + LIT_MAGIC_STRING_DATE_UL, /**< magic string id of ECMA_OBJECT_CLASS_DATE */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP + LIT_MAGIC_STRING_REGEXP_UL, /**< magic string id of ECMA_OBJECT_CLASS_REGEXP */ +#endif /* JERRY_BUILTIN_REGEXP */ + LIT_MAGIC_STRING_SYMBOL_UL, /**< magic string id of ECMA_OBJECT_CLASS_SYMBOL */ + LIT_MAGIC_STRING_STRING_ITERATOR_UL, /**< magic string id of ECMA_OBJECT_CLASS_STRING_ITERATOR */ +#if JERRY_BUILTIN_TYPEDARRAY + LIT_MAGIC_STRING_ARRAY_BUFFER_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARRAY_BUFFER */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, /**< magic string id of ECMA_OBJECT_CLASS_SHAREDARRAY_BUFFER */ +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_BIGINT + LIT_MAGIC_STRING_BIGINT_UL, /**< magic string id of ECMA_OBJECT_CLASS_BIGINT */ +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_WEAKREF + LIT_MAGIC_STRING_WEAKREF_UL, /**< magic string id of ECMA_OBJECT_CLASS_WEAKREF */ +#endif /* JERRY_BUILTIN_WEAKREF */ +}; + +JERRY_STATIC_ASSERT ((sizeof (ecma_class_object_magic_string_id) == ECMA_OBJECT_CLASS__MAX * sizeof (uint16_t)), + ecma_class_object_magic_string_id_must_have_object_class_max_elements); + +/** + * Get [[Class]] string of specified object + * + * @return class name magic string + */ +lit_magic_string_id_t +ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */ +{ + ecma_object_type_t type = ecma_get_object_type (obj_p); + + switch (type) + { + case ECMA_OBJECT_TYPE_ARRAY: + case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: + { + return LIT_MAGIC_STRING_ARRAY_UL; + } + case ECMA_OBJECT_TYPE_CLASS: + case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + switch (ext_object_p->u.cls.type) + { +#if JERRY_BUILTIN_TYPEDARRAY + case ECMA_OBJECT_CLASS_TYPEDARRAY: + { + return ecma_get_typedarray_magic_string_id ((ecma_typedarray_type_t) ext_object_p->u.cls.u1.typedarray_type); + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_CONTAINER + case ECMA_OBJECT_CLASS_CONTAINER: + { + return (lit_magic_string_id_t) ext_object_p->u.cls.u2.container_id; + } +#endif /* JERRY_BUILTIN_CONTAINER */ + default: + { + break; + } + } + + JERRY_ASSERT (ext_object_p->u.cls.type < ECMA_OBJECT_CLASS__MAX); + JERRY_ASSERT (ecma_class_object_magic_string_id[ext_object_p->u.cls.type] != LIT_MAGIC_STRING__EMPTY); + + return (lit_magic_string_id_t) ecma_class_object_magic_string_id[ext_object_p->u.cls.type]; + } + case ECMA_OBJECT_TYPE_FUNCTION: + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + return LIT_MAGIC_STRING_FUNCTION_UL; + } +#if JERRY_BUILTIN_PROXY + case ECMA_OBJECT_TYPE_PROXY: + { + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + if (!ecma_is_value_null (proxy_obj_p->target) && ecma_is_value_object (proxy_obj_p->target)) + { + ecma_object_t *target_obj_p = ecma_get_object_from_value (proxy_obj_p->target); + return ecma_object_get_class_name (target_obj_p); + } + return LIT_MAGIC_STRING_OBJECT_UL; + } +#endif /* JERRY_BUILTIN_PROXY */ + case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + switch (ext_obj_p->u.built_in.id) + { +#if JERRY_BUILTIN_MATH + case ECMA_BUILTIN_ID_MATH: + { + return LIT_MAGIC_STRING_MATH_UL; + } +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REFLECT + case ECMA_BUILTIN_ID_REFLECT: + { + return LIT_MAGIC_STRING_REFLECT_UL; + } +#endif /* JERRY_BUILTIN_REFLECT */ + case ECMA_BUILTIN_ID_GENERATOR: + { + return LIT_MAGIC_STRING_GENERATOR_UL; + } + case ECMA_BUILTIN_ID_ASYNC_GENERATOR: + { + return LIT_MAGIC_STRING_ASYNC_GENERATOR_UL; + } +#if JERRY_BUILTIN_ATOMICS + case ECMA_BUILTIN_ID_ATOMICS: + { + return LIT_MAGIC_STRING_ATOMICS_U; + } +#endif /* JERRY_BUILTIN_ATOMICS */ + default: + { + break; + } + } + + JERRY_ASSERT (ecma_object_check_class_name_is_object (obj_p)); + return LIT_MAGIC_STRING_OBJECT_UL; + } + default: + { + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL || type == ECMA_OBJECT_TYPE_PROXY); + + return LIT_MAGIC_STRING_OBJECT_UL; + } + } +} /* ecma_object_get_class_name */ + +#if JERRY_BUILTIN_REGEXP +/** + * Checks if the given argument has [[RegExpMatcher]] internal slot + * + * @return true - if the given argument is a regexp + * false - otherwise + */ +bool +ecma_object_is_regexp_object (ecma_value_t arg) /**< argument */ +{ + return (ecma_is_value_object (arg) + && ecma_object_class_is (ecma_get_object_from_value (arg), ECMA_OBJECT_CLASS_REGEXP)); +} /* ecma_object_is_regexp_object */ +#endif /* JERRY_BUILTIN_REGEXP */ + +/** + * Object's IsConcatSpreadable operation, used for Array.prototype.concat + * It checks the argument's [Symbol.isConcatSpreadable] property value + * + * See also: + * ECMA-262 v6, 22.1.3.1.1; + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the argument is concatSpreadable + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +ecma_op_is_concat_spreadable (ecma_value_t arg) /**< argument */ +{ + if (!ecma_is_value_object (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t spreadable = + ecma_op_object_get_by_symbol_id (ecma_get_object_from_value (arg), LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE); + + if (ECMA_IS_VALUE_ERROR (spreadable)) + { + return spreadable; + } + + if (!ecma_is_value_undefined (spreadable)) + { + const bool to_bool = ecma_op_to_boolean (spreadable); + ecma_free_value (spreadable); + return ecma_make_boolean_value (to_bool); + } + + return ecma_is_value_array (arg); +} /* ecma_op_is_concat_spreadable */ + +/** + * IsRegExp operation + * + * See also: + * ECMA-262 v6, 22.1.3.1.1; + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the argument is regexp + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +ecma_op_is_regexp (ecma_value_t arg) /**< argument */ +{ + if (!ecma_is_value_object (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t is_regexp = ecma_op_object_get_by_symbol_id (ecma_get_object_from_value (arg), LIT_GLOBAL_SYMBOL_MATCH); + + if (ECMA_IS_VALUE_ERROR (is_regexp)) + { + return is_regexp; + } + + if (!ecma_is_value_undefined (is_regexp)) + { + const bool to_bool = ecma_op_to_boolean (is_regexp); + ecma_free_value (is_regexp); + return ecma_make_boolean_value (to_bool); + } + + return ecma_make_boolean_value (ecma_object_is_regexp_object (arg)); +} /* ecma_op_is_regexp */ + +/** + * SpeciesConstructor operation + * See also: + * ECMA-262 v6, 7.3.20; + * + * @return ecma_value + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_species_constructor (ecma_object_t *this_value, /**< This Value */ + ecma_builtin_id_t default_constructor_id) /**< Builtin ID of default constructor */ +{ + ecma_object_t *default_constructor_p = ecma_builtin_get (default_constructor_id); + ecma_value_t constructor = ecma_op_object_get_by_magic_id (this_value, LIT_MAGIC_STRING_CONSTRUCTOR); + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return constructor; + } + + if (ecma_is_value_undefined (constructor)) + { + ecma_ref_object (default_constructor_p); + return ecma_make_object_value (default_constructor_p); + } + + if (!ecma_is_value_object (constructor)) + { + ecma_free_value (constructor); + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTOR_NOT_AN_OBJECT); + } + + ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); + ecma_value_t species = ecma_op_object_get_by_symbol_id (ctor_object_p, LIT_GLOBAL_SYMBOL_SPECIES); + ecma_deref_object (ctor_object_p); + + if (ECMA_IS_VALUE_ERROR (species)) + { + return species; + } + + if (ecma_is_value_undefined (species) || ecma_is_value_null (species)) + { + ecma_ref_object (default_constructor_p); + return ecma_make_object_value (default_constructor_p); + } + + if (!ecma_is_constructor (species)) + { + ecma_free_value (species); + return ecma_raise_type_error (ECMA_ERR_SPECIES_MUST_BE_A_CONSTRUCTOR); + } + + return species; +} /* ecma_op_species_constructor */ + +/** + * 7.3.18 Abstract operation Invoke when property name is a magic string + * + * @return ecma_value result of the invoked function or raised error + * note: returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_invoke_by_symbol_id (ecma_value_t object, /**< Object value */ + lit_magic_string_id_t symbol_id, /**< Symbol ID */ + ecma_value_t *args_p, /**< Argument list */ + uint32_t args_len) /**< Argument list length */ +{ + ecma_string_t *symbol_p = ecma_op_get_global_symbol (symbol_id); + ecma_value_t ret_value = ecma_op_invoke (object, symbol_p, args_p, args_len); + ecma_deref_ecma_string (symbol_p); + + return ret_value; +} /* ecma_op_invoke_by_symbol_id */ + +/** + * 7.3.18 Abstract operation Invoke when property name is a magic string + * + * @return ecma_value result of the invoked function or raised error + * note: returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_invoke_by_magic_id (ecma_value_t object, /**< Object value */ + lit_magic_string_id_t magic_string_id, /**< Magic string ID */ + ecma_value_t *args_p, /**< Argument list */ + uint32_t args_len) /**< Argument list length */ +{ + return ecma_op_invoke (object, ecma_get_magic_string (magic_string_id), args_p, args_len); +} /* ecma_op_invoke_by_magic_id */ + +/** + * 7.3.18 Abstract operation Invoke + * + * @return ecma_value result of the invoked function or raised error + * note: returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_invoke (ecma_value_t object, /**< Object value */ + ecma_string_t *property_name_p, /**< Property name */ + ecma_value_t *args_p, /**< Argument list */ + uint32_t args_len) /**< Argument list length */ +{ + /* 3. */ + ecma_value_t object_value = ecma_op_to_object (object); + if (ECMA_IS_VALUE_ERROR (object_value)) + { + return object_value; + } + + ecma_object_t *object_p = ecma_get_object_from_value (object_value); + + ecma_value_t func = ecma_op_object_get_with_receiver (object_p, property_name_p, object); + + if (ECMA_IS_VALUE_ERROR (func)) + { + ecma_deref_object (object_p); + return func; + } + + /* 4. */ + ecma_value_t call_result = ecma_op_function_validated_call (func, object, args_p, args_len); + ecma_free_value (func); + + ecma_deref_object (object_p); + + return call_result; +} /* ecma_op_invoke */ + +/** + * Ordinary object [[GetPrototypeOf]] operation + * + * See also: + * ECMAScript v6, 9.1.1 + * + * @return the value of the [[Prototype]] internal slot of the given object. + */ +jmem_cpointer_t +ecma_op_ordinary_object_get_prototype_of (ecma_object_t *obj_p) /**< object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); + + return obj_p->u2.prototype_cp; +} /* ecma_op_ordinary_object_get_prototype_of */ + +/** + * Ordinary object [[SetPrototypeOf]] operation + * + * See also: + * ECMAScript v6, 9.1.2 + * + * @return ECMA_VALUE_FALSE - if the operation fails + * ECMA_VALUE_TRUE - otherwise + */ +ecma_value_t +ecma_op_ordinary_object_set_prototype_of (ecma_object_t *obj_p, /**< base object */ + ecma_value_t proto) /**< prototype object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); + + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (proto) || ecma_is_value_null (proto)); + + /* 3. */ + ecma_object_t *current_proto_p = ECMA_GET_POINTER (ecma_object_t, ecma_op_ordinary_object_get_prototype_of (obj_p)); + ecma_object_t *new_proto_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); + + /* 4. */ + if (new_proto_p == current_proto_p) + { + return ECMA_VALUE_TRUE; + } + + /* 2 - 5. */ + if (!ecma_op_ordinary_object_is_extensible (obj_p)) + { + return ECMA_VALUE_FALSE; + } + + /** + * When the prototype of a fast array changes, it is required to convert the + * array to a "normal" array. This ensures that all [[Get]]/[[Set]]/etc. + * calls works as expected. + */ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + + /* 6. */ + ecma_object_t *iter_p = new_proto_p; + + /* 7 - 8. */ + while (true) + { + /* 8.a */ + if (iter_p == NULL) + { + break; + } + + /* 8.b */ + if (obj_p == iter_p) + { + return ECMA_VALUE_FALSE; + } + + /* 8.c.i */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (iter_p)) + { + /** + * Prevent setting 'Object.prototype.__proto__' + * to avoid circular referencing in the prototype chain. + */ + if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE)) + { + return ECMA_VALUE_FALSE; + } + + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 8.c.ii */ + iter_p = ECMA_GET_POINTER (ecma_object_t, ecma_op_ordinary_object_get_prototype_of (iter_p)); + } + + /* 9. */ + ECMA_SET_POINTER (obj_p->u2.prototype_cp, new_proto_p); + + /* 10. */ + return ECMA_VALUE_TRUE; +} /* ecma_op_ordinary_object_set_prototype_of */ + +/** + * [[IsExtensible]] operation for Ordinary object. + * + * See also: + * ECMAScript v6, 9.1.2 + * + * @return true - if object is extensible + * false - otherwise + */ +bool JERRY_ATTR_PURE +ecma_op_ordinary_object_is_extensible (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + bool is_extensible = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_EXTENSIBLE) != 0; + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p) || is_extensible); + + return is_extensible; +} /* ecma_op_ordinary_object_is_extensible */ + +/** + * Set value of [[Extensible]] object's internal property. + * + * @return void + */ +void JERRY_ATTR_NOINLINE +ecma_op_ordinary_object_prevent_extensions (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (object_p))) + { + ecma_fast_array_convert_to_normal (object_p); + } + + object_p->type_flags_refs &= (ecma_object_descriptor_t) ~ECMA_OBJECT_FLAG_EXTENSIBLE; +} /* ecma_op_ordinary_object_prevent_extensions */ + +/** + * Checks whether an object (excluding prototypes) has a named property + * + * @return true - if property is found + * false - otherwise + */ +ecma_value_t +ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + ecma_property_t property = + ecma_op_object_get_own_property (object_p, property_name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); + +#if JERRY_BUILTIN_TYPEDARRAY + if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + + JERRY_ASSERT (ECMA_PROPERTY_IS_FOUND (property) || property == ECMA_PROPERTY_TYPE_NOT_FOUND + || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + + return ecma_make_boolean_value (ECMA_PROPERTY_IS_FOUND (property)); +} /* ecma_op_ordinary_object_has_own_property */ + +/** + * Checks whether an object (excluding prototypes) has a named property. Handles proxy objects too. + * + * @return true - if property is found + * false - otherwise + */ +ecma_value_t +ecma_op_object_has_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (object_p)) + { + ecma_property_descriptor_t prop_desc; + + ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (object_p, property_name_p, &prop_desc); + + if (ecma_is_value_true (status)) + { + ecma_free_property_descriptor (&prop_desc); + } + + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ecma_op_ordinary_object_has_own_property (object_p, property_name_p); +} /* ecma_op_object_has_own_property */ + +#if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER + +/** + * Set a weak reference from a container or WeakRefObject to a key object + */ +void +ecma_op_object_set_weak (ecma_object_t *object_p, /**< key object */ + ecma_object_t *target_p) /**< target object */ +{ + if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (object_p))) + { + ecma_fast_array_convert_to_normal (object_p); + } + + ecma_string_t *weak_refs_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_WEAK_REFS); + ecma_property_t *property_p = ecma_find_named_property (object_p, weak_refs_string_p); + ecma_collection_t *refs_p; + + if (property_p == NULL) + { + refs_p = ecma_new_collection (); + + ecma_property_value_t *value_p; + ECMA_CREATE_INTERNAL_PROPERTY (object_p, weak_refs_string_p, property_p, value_p); + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, refs_p); + } + else + { + refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, (ECMA_PROPERTY_VALUE_PTR (property_p)->value)); + } + + const ecma_value_t target_value = ecma_make_object_value ((ecma_object_t *) target_p); + for (uint32_t i = 0; i < refs_p->item_count; i++) + { + if (ecma_is_value_empty (refs_p->buffer_p[i])) + { + refs_p->buffer_p[i] = target_value; + return; + } + } + + ecma_collection_push_back (refs_p, target_value); +} /* ecma_op_object_set_weak */ + +/** + * Helper function to remove a weak reference to an object. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +void +ecma_op_object_unref_weak (ecma_object_t *object_p, /**< this argument */ + ecma_value_t ref_holder) /**< key argument */ +{ + ecma_string_t *weak_refs_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_WEAK_REFS); + + ecma_property_t *property_p = ecma_find_named_property (object_p, weak_refs_string_p); + JERRY_ASSERT (property_p != NULL); + + ecma_collection_t *refs_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, ECMA_PROPERTY_VALUE_PTR (property_p)->value); + ecma_value_t *buffer_p = refs_p->buffer_p; + + while (true) + { + if (*buffer_p == ref_holder) + { + *buffer_p = ECMA_VALUE_EMPTY; + return; + } + JERRY_ASSERT (buffer_p < refs_p->buffer_p + refs_p->item_count); + buffer_p++; + } +} /* ecma_op_object_unref_weak */ + +#endif /* JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER */ +/** + * Raise property redefinition error + * + * @return ECMA_VALUE_FALSE - if JERRY_PROP_SHOULD_THROW is not set + * raised TypeError - otherwise + */ +ecma_value_t +ecma_raise_property_redefinition (ecma_string_t *property_name_p, /**< property name */ + uint16_t flags) /**< property descriptor flags */ +{ + JERRY_UNUSED (property_name_p); + + return ECMA_REJECT_WITH_FORMAT (flags & JERRY_PROP_SHOULD_THROW, + "Cannot redefine property: %", + ecma_make_prop_name_value (property_name_p)); +} /* ecma_raise_property_redefinition */ + +/** + * Raise readonly assignment error + * + * @return ECMA_VALUE_FALSE - if is_throw is true + * raised TypeError - otherwise + */ +ecma_value_t +ecma_raise_readonly_assignment (ecma_string_t *property_name_p, /**< property name */ + bool is_throw) /**< is throw flag */ +{ + JERRY_UNUSED (property_name_p); + + return ECMA_REJECT_WITH_FORMAT (is_throw, + "Cannot assign to read only property '%'", + ecma_make_prop_name_value (property_name_p)); +} /* ecma_raise_readonly_assignment */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.h new file mode 100644 index 00000000..87e25388 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-objects.h @@ -0,0 +1,147 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_OBJECTS_H +#define ECMA_OBJECTS_H + +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaobjectsinternalops ECMA objects' operations + * @{ + */ + +#if JERRY_ERROR_MESSAGES +/** + * Reject with TypeError depending on 'is_throw' with the given format + */ +#define ECMA_REJECT_WITH_FORMAT(is_throw, msg, ...) \ + ((is_throw) ? ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, (msg), __VA_ARGS__) : ECMA_VALUE_FALSE) + +/** + * Reject with TypeError depending on 'is_throw' with the given message + */ +#define ECMA_REJECT(is_throw, msg) ((is_throw) ? ecma_raise_type_error (msg) : ECMA_VALUE_FALSE) +#else /* !JERRY_ERROR_MESSAGES */ +/** + * Reject with TypeError depending on is_throw flags wit the given format + */ +#define ECMA_REJECT_WITH_FORMAT(is_throw, msg, ...) ECMA_REJECT ((is_throw), (msg)) + +/** + * Reject with TypeError depending on is_throw flags wit the given message + */ +#define ECMA_REJECT(is_throw, msg) ((is_throw) ? ecma_raise_type_error (ECMA_ERR_EMPTY) : ECMA_VALUE_FALSE) +#endif /* JERRY_ERROR_MESSAGES */ + +ecma_value_t ecma_raise_property_redefinition (ecma_string_t *property_name_p, uint16_t flags); +ecma_value_t ecma_raise_readonly_assignment (ecma_string_t *property_name_p, bool is_throw); + +ecma_property_t ecma_op_object_get_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_property_ref_t *property_ref_p, + uint32_t options); +ecma_value_t ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_has_property (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_find_own (ecma_value_t base_value, ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_find (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_find_by_index (ecma_object_t *object_p, ecma_length_t index); +ecma_value_t ecma_op_object_get (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t +ecma_op_object_get_with_receiver (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_op_object_get_length (ecma_object_t *object_p, ecma_length_t *length_p); +ecma_value_t ecma_op_object_get_by_index (ecma_object_t *object_p, ecma_length_t index); +ecma_value_t ecma_op_object_get_by_magic_id (ecma_object_t *object_p, lit_magic_string_id_t property_id); +ecma_string_t *ecma_op_get_global_symbol (lit_magic_string_id_t property_id); +bool ecma_op_compare_string_to_global_symbol (ecma_string_t *string_p, lit_magic_string_id_t property_id); +ecma_value_t ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, lit_magic_string_id_t property_id); +ecma_value_t ecma_op_get_method_by_symbol_id (ecma_value_t value, lit_magic_string_id_t symbol_id); +ecma_value_t ecma_op_get_method_by_magic_id (ecma_value_t value, lit_magic_string_id_t magic_id); +ecma_value_t ecma_op_object_put_with_receiver (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t +ecma_op_object_put (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_value_t value, bool is_throw); +ecma_value_t ecma_op_object_put_with_receiver (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t +ecma_op_object_put_by_index (ecma_object_t *object_p, ecma_length_t index, ecma_value_t value, bool is_throw); +ecma_value_t ecma_op_object_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_throw); +ecma_value_t ecma_op_object_delete_by_index (ecma_object_t *obj_p, ecma_length_t index, bool is_throw); +ecma_value_t ecma_op_object_default_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); +ecma_value_t ecma_op_object_define_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, + ecma_string_t *property_name_p, + ecma_property_descriptor_t *prop_desc_p); +ecma_value_t ecma_op_object_has_instance (ecma_object_t *obj_p, ecma_value_t value); +ecma_object_t *ecma_op_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_value_t ecma_op_object_is_prototype_of (ecma_object_t *base_p, ecma_object_t *target_p); +ecma_collection_t *ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, + ecma_enumerable_property_names_options_t option); +ecma_collection_t *ecma_op_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); +ecma_collection_t *ecma_op_object_enumerate (ecma_object_t *obj_p); + +lit_magic_string_id_t ecma_object_get_class_name (ecma_object_t *obj_p); +#if JERRY_BUILTIN_REGEXP +bool ecma_object_is_regexp_object (ecma_value_t arg); +#endif /* JERRY_BUILTIN_REGEXP */ +ecma_value_t ecma_op_is_concat_spreadable (ecma_value_t arg); +ecma_value_t ecma_op_is_regexp (ecma_value_t arg); +ecma_value_t ecma_op_species_constructor (ecma_object_t *this_value, ecma_builtin_id_t default_constructor_id); +ecma_value_t ecma_op_invoke_by_symbol_id (ecma_value_t object, + lit_magic_string_id_t magic_string_id, + ecma_value_t *args_p, + uint32_t args_len); +#if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER +void ecma_op_object_set_weak (ecma_object_t *object_p, ecma_object_t *target_p); +void ecma_op_object_unref_weak (ecma_object_t *object_p, ecma_value_t ref_holder); +#endif /* JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER */ +ecma_value_t +ecma_op_invoke (ecma_value_t object, ecma_string_t *property_name_p, ecma_value_t *args_p, uint32_t args_len); +ecma_value_t ecma_op_invoke_by_magic_id (ecma_value_t object, + lit_magic_string_id_t magic_string_id, + ecma_value_t *args_p, + uint32_t args_len); + +jmem_cpointer_t ecma_op_ordinary_object_get_prototype_of (ecma_object_t *obj_p); +ecma_value_t ecma_op_ordinary_object_set_prototype_of (ecma_object_t *base_p, ecma_value_t proto); +bool JERRY_ATTR_PURE ecma_op_ordinary_object_is_extensible (ecma_object_t *object_p); +void ecma_op_ordinary_object_prevent_extensions (ecma_object_t *object_p); + +#if JERRY_BUILTIN_PROXY +ecma_value_t ecma_op_get_own_property_descriptor (ecma_value_t target, + ecma_string_t *property_name_p, + ecma_property_descriptor_t *prop_desc_p); +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_OBJECTS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.cpp new file mode 100644 index 00000000..333aa202 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.cpp @@ -0,0 +1,1237 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-promise-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-boolean-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-jobqueue.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmapromiseobject ECMA Promise object related routines + * @{ + */ + +/** + * Check if an object is promise. + * + * @return true - if the object is a promise. + * false - otherwise. + */ +bool +ecma_is_promise (ecma_object_t *obj_p) /**< points to object */ +{ + return ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_PROMISE); +} /* ecma_is_promise */ + +/** + * Get the result of the promise. + * + * @return ecma value of the promise result. + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_promise_get_result (ecma_object_t *obj_p) /**< points to promise object */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + return ecma_copy_value (ext_object_p->u.cls.u3.value); +} /* ecma_promise_get_result */ + +/** + * Set the PromiseResult of promise. + * + * @return void + */ +static inline void +ecma_promise_set_result (ecma_object_t *obj_p, /**< points to promise object */ + ecma_value_t result) /**< the result value */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + JERRY_ASSERT (ext_object_p->u.cls.u3.value == ECMA_VALUE_UNDEFINED); + + ext_object_p->u.cls.u3.value = result; +} /* ecma_promise_set_result */ + +/** + * Get the PromiseState of promise. + * + * @return the state's enum value + */ +uint8_t +ecma_promise_get_flags (ecma_object_t *obj_p) /**< points to promise object */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + + return ((ecma_extended_object_t *) obj_p)->u.cls.u1.promise_flags; +} /* ecma_promise_get_flags */ + +/** + * Set the PromiseState of promise. + * + * @return void + */ +static inline void +ecma_promise_set_state (ecma_object_t *obj_p, /**< points to promise object */ + bool is_fulfilled) /**< new flags */ +{ + JERRY_ASSERT (ecma_is_promise (obj_p)); + JERRY_ASSERT (ecma_promise_get_flags (obj_p) & ECMA_PROMISE_IS_PENDING); + + uint8_t flags_to_invert = + (is_fulfilled ? (ECMA_PROMISE_IS_PENDING | ECMA_PROMISE_IS_FULFILLED) : ECMA_PROMISE_IS_PENDING); + + ((ecma_extended_object_t *) obj_p)->u.cls.u1.promise_flags ^= flags_to_invert; +} /* ecma_promise_set_state */ + +/** + * Take a collection of Reactions and enqueue a new PromiseReactionJob for each Reaction. + * + * See also: ES2015 25.4.1.8 + */ +static void +ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reactions */ + ecma_value_t value, /**< value for resolve or reject */ + bool is_reject) /**< true if promise is rejected, false otherwise */ +{ + ecma_value_t *buffer_p = reactions->buffer_p; + ecma_value_t *buffer_end_p = buffer_p + reactions->item_count; + + while (buffer_p < buffer_end_p) + { + ecma_value_t object_with_tag = *buffer_p++; + ecma_object_t *object_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, object_with_tag); + ecma_value_t object = ecma_make_object_value (object_p); + + if (JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG (object_with_tag)) + { + ecma_enqueue_promise_async_reaction_job (object, value, is_reject); + continue; + } + + if (!is_reject) + { + ecma_value_t handler = ECMA_VALUE_TRUE; + + if (JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (object_with_tag)) + { + handler = *buffer_p++; + } + + ecma_enqueue_promise_reaction_job (object, handler, value); + } + else if (JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (object_with_tag)) + { + buffer_p++; + } + + if (is_reject) + { + ecma_value_t handler = ECMA_VALUE_FALSE; + + if (JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (object_with_tag)) + { + handler = *buffer_p++; + } + + ecma_enqueue_promise_reaction_job (object, handler, value); + } + else if (JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (object_with_tag)) + { + buffer_p++; + } + } +} /* ecma_promise_trigger_reactions */ + +/** + * Checks whether a resolver is called before. + * + * @return true if it was called before, false otherwise + */ +static inline bool +ecma_is_resolver_already_called (ecma_object_t *promise_obj_p) /**< promise */ +{ + return (ecma_promise_get_flags (promise_obj_p) & ECMA_PROMISE_ALREADY_RESOLVED) != 0; +} /* ecma_is_resolver_already_called */ + +/** + * Reject a Promise with a reason. + * + * See also: ES2015 25.4.1.7 + */ +void +ecma_reject_promise (ecma_value_t promise, /**< promise */ + ecma_value_t reason) /**< reason for reject */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (promise); + + JERRY_ASSERT (ecma_promise_get_flags (obj_p) & ECMA_PROMISE_IS_PENDING); + + ecma_promise_set_state (obj_p, false); + ecma_promise_set_result (obj_p, ecma_copy_value_if_not_object (reason)); + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) obj_p; + + /* GC can be triggered by ecma_new_collection so freeing the collection + first and creating a new one might cause a heap after use event. */ + ecma_collection_t *reactions = promise_p->reactions; + + /* Fulfill reactions will never be triggered. */ + ecma_promise_trigger_reactions (reactions, reason, true); + + promise_p->reactions = ecma_new_collection (); + + ecma_collection_destroy (reactions); +} /* ecma_reject_promise */ + +/** + * Fulfill a Promise with a value. + * + * See also: ES2015 25.4.1.4 + */ +void +ecma_fulfill_promise (ecma_value_t promise, /**< promise */ + ecma_value_t value) /**< fulfilled value */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (promise); + + JERRY_ASSERT (ecma_promise_get_flags (obj_p) & ECMA_PROMISE_IS_PENDING); + + if (promise == value) + { + ecma_raise_type_error (ECMA_ERR_PROMISE_RESOLVE_ITSELF); + ecma_value_t exception = jcontext_take_exception (); + ecma_reject_promise (promise, exception); + ecma_free_value (exception); + return; + } + + if (ecma_is_value_object (value)) + { + ecma_value_t then = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (value), LIT_MAGIC_STRING_THEN); + + if (ECMA_IS_VALUE_ERROR (then)) + { + then = jcontext_take_exception (); + ecma_reject_promise (promise, then); + ecma_free_value (then); + return; + } + + if (ecma_op_is_callable (then)) + { + ecma_enqueue_promise_resolve_thenable_job (promise, value, then); + ecma_free_value (then); + return; + } + + ecma_free_value (then); + } + + ecma_promise_set_state (obj_p, true); + ecma_promise_set_result (obj_p, ecma_copy_value_if_not_object (value)); + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) obj_p; + + /* GC can be triggered by ecma_new_collection so freeing the collection + first and creating a new one might cause a heap after use event. */ + ecma_collection_t *reactions = promise_p->reactions; + + /* Reject reactions will never be triggered. */ + ecma_promise_trigger_reactions (reactions, value, false); + + promise_p->reactions = ecma_new_collection (); + + ecma_collection_destroy (reactions); +} /* ecma_fulfill_promise */ + +/** + * Reject a Promise with a reason. Sanity checks are performed before the reject. + * + * See also: ES2015 25.4.1.3.1 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_reject_promise_with_checks (ecma_value_t promise, /**< promise */ + ecma_value_t reason) /**< reason for reject */ +{ + /* 1. */ + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + JERRY_ASSERT (ecma_is_promise (promise_obj_p)); + + /* 3., 4. */ + if (JERRY_UNLIKELY (ecma_is_resolver_already_called (promise_obj_p))) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 5. */ + ((ecma_extended_object_t *) promise_obj_p)->u.cls.u1.promise_flags |= ECMA_PROMISE_ALREADY_RESOLVED; + + /* 6. */ + ecma_reject_promise (promise, reason); + return ECMA_VALUE_UNDEFINED; +} /* ecma_reject_promise_with_checks */ + +/** + * Fulfill a Promise with a value. Sanity checks are performed before the resolve. + * + * See also: ES2015 25.4.1.3.2 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_fulfill_promise_with_checks (ecma_value_t promise, /**< promise */ + ecma_value_t value) /**< fulfilled value */ +{ + /* 1. */ + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + JERRY_ASSERT (ecma_is_promise (promise_obj_p)); + + /* 3., 4. */ + if (JERRY_UNLIKELY (ecma_is_resolver_already_called (promise_obj_p))) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 5. */ + ((ecma_extended_object_t *) promise_obj_p)->u.cls.u1.promise_flags |= ECMA_PROMISE_ALREADY_RESOLVED; + + ecma_fulfill_promise (promise, value); + return ECMA_VALUE_UNDEFINED; +} /* ecma_fulfill_promise_with_checks */ + +/** + * Native handler for Promise Reject Function. + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_promise_reject_handler (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_promise_resolver_t *function_p = (ecma_promise_resolver_t *) function_obj_p; + + ecma_value_t reject_value = (args_count == 0) ? ECMA_VALUE_UNDEFINED : args_p[0]; + return ecma_reject_promise_with_checks (function_p->promise, reject_value); +} /* ecma_promise_reject_handler */ + +/** + * Native handler for Promise Resolve Function. + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_promise_resolve_handler (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_promise_resolver_t *function_p = (ecma_promise_resolver_t *) function_obj_p; + + ecma_value_t fulfilled_value = (args_count == 0) ? ECMA_VALUE_UNDEFINED : args_p[0]; + return ecma_fulfill_promise_with_checks (function_p->promise, fulfilled_value); +} /* ecma_promise_resolve_handler */ + +/** + * Helper function for PromiseCreateResolvingFunctions. + * + * See also: ES2015 25.4.1.3 2. - 7. + * + * @return pointer to the resolving function + */ +static ecma_object_t * +ecma_promise_create_resolving_function (ecma_object_t *promise_p, /**< Promise Object */ + ecma_native_handler_id_t id) /**< Callback handler */ +{ + ecma_object_t *func_obj_p = ecma_op_create_native_handler (id, sizeof (ecma_promise_resolver_t)); + + ecma_promise_resolver_t *resolver_p = (ecma_promise_resolver_t *) func_obj_p; + resolver_p->promise = ecma_make_object_value (promise_p); + + return func_obj_p; +} /* ecma_promise_create_resolving_function */ + +/** + * Helper function for running an executor. + * + * @return ecma value of the executor callable + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_promise_run_executor (ecma_object_t *promise_p, /**< Promise Object */ + ecma_value_t executor, /**< executor function */ + ecma_value_t this_value) /**< this value */ +{ + ecma_object_t *resolve_func_p, *reject_func_p; + resolve_func_p = ecma_promise_create_resolving_function (promise_p, ECMA_NATIVE_HANDLER_PROMISE_RESOLVE); + reject_func_p = ecma_promise_create_resolving_function (promise_p, ECMA_NATIVE_HANDLER_PROMISE_REJECT); + + ecma_value_t argv[] = { ecma_make_object_value (resolve_func_p), ecma_make_object_value (reject_func_p) }; + ecma_value_t result = ecma_op_function_call (ecma_get_object_from_value (executor), this_value, argv, 2); + ecma_deref_object (resolve_func_p); + ecma_deref_object (reject_func_p); + + return result; +} /* ecma_promise_run_executor */ + +/** + * Create a promise object. + * + * See also: ES2015 25.4.3.1 + * + * @return ecma value of the new promise object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function or ECMA_VALUE_EMPTY */ + ecma_value_t parent, /**< parent promise if available */ + ecma_object_t *new_target_p) /**< new.target value */ +{ + JERRY_UNUSED (parent); + + if (new_target_p == NULL) + { + new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE); + } + + /* 3. */ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* Calling ecma_new_collection might trigger a GC call, so this + * allocation is performed before the object is constructed. */ + ecma_collection_t *reactions = ecma_new_collection (); + + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_promise_object_t), ECMA_OBJECT_TYPE_CLASS); + ecma_deref_object (proto_p); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_PROMISE; + /* 5 */ + ext_object_p->u.cls.u1.promise_flags = ECMA_PROMISE_IS_PENDING; + ext_object_p->u.cls.u3.value = ECMA_VALUE_UNDEFINED; + + /* 6-8. */ + ecma_promise_object_t *promise_object_p = (ecma_promise_object_t *) object_p; + promise_object_p->reactions = reactions; + + /* 9. */ + ecma_value_t completion = ECMA_VALUE_UNDEFINED; + + if (executor != ECMA_VALUE_EMPTY) + { + JERRY_ASSERT (ecma_op_is_callable (executor)); + + completion = ecma_promise_run_executor (object_p, executor, ECMA_VALUE_UNDEFINED); + } + + ecma_value_t status = ECMA_VALUE_EMPTY; + + if (ECMA_IS_VALUE_ERROR (completion)) + { + /* 10.a. */ + completion = jcontext_take_exception (); + ecma_reject_promise_with_checks (ecma_make_object_value (object_p), completion); + } + + ecma_free_value (completion); + + /* 10.b. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_deref_object (object_p); + return status; + } + + /* 11. */ + ecma_free_value (status); + return ecma_make_object_value (object_p); +} /* ecma_op_create_promise_object */ + +/** + * Helper function for increase or decrease the remaining count. + * + * @return the current remaining count after increase or decrease. + */ +uint32_t +ecma_promise_remaining_inc_or_dec (ecma_value_t remaining, /**< the remaining count */ + bool is_inc) /**< whether to increase the count */ +{ + JERRY_ASSERT (ecma_is_value_object (remaining)); + + ecma_object_t *remaining_p = ecma_get_object_from_value (remaining); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) remaining_p; + + JERRY_ASSERT (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_NUMBER); + + JERRY_ASSERT (ecma_is_value_integer_number (ext_object_p->u.cls.u3.value)); + + uint32_t current = (uint32_t) ecma_get_integer_from_value (ext_object_p->u.cls.u3.value); + + if (is_inc) + { + current++; + } + else + { + current--; + } + ext_object_p->u.cls.u3.value = ecma_make_uint32_value (current); + + return current; +} /* ecma_promise_remaining_inc_or_dec */ + +/** + * Native handler for Promise.all and Promise.allSettled Resolve Element Function. + * + * See also: + * ES2015 25.4.4.1.2 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_promise_all_or_all_settled_handler_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + ecma_value_t arg = args_count > 0 ? args_p[0] : ECMA_VALUE_UNDEFINED; + + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) function_obj_p; + uint8_t promise_type = executor_p->header.u.built_in.u2.routine_flags; + + promise_type = (uint8_t) (promise_type >> ECMA_NATIVE_HANDLER_COMMON_FLAGS_SHIFT); + + /* 1 - 2. */ + if (executor_p->index == 0) + { + return ECMA_VALUE_UNDEFINED; + } + + if (promise_type == ECMA_PROMISE_ALL_RESOLVE || promise_type == ECMA_PROMISE_ANY_REJECT) + { + /* 8. */ + ecma_op_object_put_by_index (ecma_get_object_from_value (executor_p->values), + (uint32_t) (executor_p->index - 1), + arg, + false); + } + else + { + lit_magic_string_id_t status_property_val = LIT_MAGIC_STRING_REJECTED; + lit_magic_string_id_t data_propery_name = LIT_MAGIC_STRING_REASON; + + if (promise_type == ECMA_PROMISE_ALLSETTLED_RESOLVE) + { + status_property_val = LIT_MAGIC_STRING_FULFILLED; + data_propery_name = LIT_MAGIC_STRING_VALUE; + } + + ecma_object_t *obj_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_STATUS), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + prop_value_p->value = ecma_make_magic_string_value (status_property_val); + + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (data_propery_name), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = ecma_copy_value_if_not_object (arg); + + ecma_value_t obj_val = ecma_make_object_value (obj_p); + /* 12. */ + ecma_op_object_put_by_index (ecma_get_object_from_value (executor_p->values), + (uint32_t) (executor_p->index - 1), + obj_val, + false); + ecma_deref_object (obj_p); + } + /* 3. */ + executor_p->index = 0; + + /* 9-10. */ + ecma_value_t ret = ECMA_VALUE_UNDEFINED; + if (ecma_promise_remaining_inc_or_dec (executor_p->remaining_elements, false) == 0) + { + ecma_value_t capability = executor_p->capability; + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) ecma_get_object_from_value (capability); + if (promise_type == ECMA_PROMISE_ANY_REJECT) + { + ecma_value_t error_val = ecma_new_aggregate_error (executor_p->values, ECMA_VALUE_UNDEFINED); + ret = + ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &error_val, 1); + ecma_free_value (error_val); + } + else + { + ret = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &executor_p->values, + 1); + } + } + + return ret; +} /* ecma_promise_all_or_all_settled_handler_cb */ + +/** + * GetCapabilitiesExecutor Functions + * + * Checks and sets a promiseCapability's resolve and reject properties. + * + * See also: ES11 25.6.1.5.1 + * + * @return ECMA_VALUE_UNDEFINED or TypeError + * returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_get_capabilities_executor_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + /* 1. */ + ecma_promise_capability_executor_t *executor_p = (ecma_promise_capability_executor_t *) function_obj_p; + + /* 2-3. */ + ecma_object_t *capability_obj_p = ecma_get_object_from_value (executor_p->capability); + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + /* 4. */ + if (!ecma_is_value_undefined (capability_p->resolve)) + { + return ecma_raise_type_error (ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED); + } + + /* 5. */ + if (!ecma_is_value_undefined (capability_p->reject)) + { + return ecma_raise_type_error (ECMA_ERR_REJECT_MUST_BE_UNDEFINED); + } + + /* 6. */ + capability_p->resolve = (args_count > 0) ? args_p[0] : ECMA_VALUE_UNDEFINED; + /* 7. */ + capability_p->reject = (args_count > 1) ? args_p[1] : ECMA_VALUE_UNDEFINED; + + /* 8. */ + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_get_capabilities_executor_cb */ + +/** + * Create a new PromiseCapability. + * + * See also: ES11 25.6.1.5 + * + * @return NULL - if the operation raises error + * new PromiseCapability object - otherwise + */ +ecma_object_t * +ecma_promise_new_capability (ecma_value_t constructor, /**< constructor function */ + ecma_value_t parent) /**< parent promise if available */ +{ + /* 1. */ + if (!ecma_is_constructor (constructor)) + { + ecma_raise_type_error (ECMA_ERR_INVALID_CAPABILITY); + return NULL; + } + + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); + + /* 3. */ + ecma_object_t *capability_obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), + sizeof (ecma_promise_capabality_t), + ECMA_OBJECT_TYPE_CLASS); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + capability_p->header.u.cls.type = ECMA_OBJECT_CLASS_PROMISE_CAPABILITY; + capability_p->header.u.cls.u3.promise = ECMA_VALUE_UNDEFINED; + capability_p->resolve = ECMA_VALUE_UNDEFINED; + capability_p->reject = ECMA_VALUE_UNDEFINED; + + /* 4-5. */ + ecma_object_t *executor_p = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR, + sizeof (ecma_promise_capability_executor_t)); + + /* 6. */ + ecma_promise_capability_executor_t *executor_func_p = (ecma_promise_capability_executor_t *) executor_p; + executor_func_p->capability = ecma_make_object_value (capability_obj_p); + + /* 7. */ + ecma_value_t executor = ecma_make_object_value (executor_p); + ecma_value_t promise; + + if (constructor_obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)) + { + promise = ecma_op_create_promise_object (executor, parent, constructor_obj_p); + } + else + { + promise = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &executor, 1); + } + + ecma_deref_object (executor_p); + + if (ECMA_IS_VALUE_ERROR (promise)) + { + ecma_deref_object (capability_obj_p); + return NULL; + } + + /* 8. */ + if (!ecma_op_is_callable (capability_p->resolve)) + { + ecma_free_value (promise); + ecma_deref_object (capability_obj_p); + ecma_raise_type_error (ECMA_ERR_PARAMETER_RESOLVE_MUST_BE_CALLABLE); + return NULL; + } + + /* 9. */ + if (!ecma_op_is_callable (capability_p->reject)) + { + ecma_free_value (promise); + ecma_deref_object (capability_obj_p); + ecma_raise_type_error (ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE); + return NULL; + } + + /* 10. */ + capability_p->header.u.cls.u3.promise = promise; + + ecma_free_value (promise); + + /* 11. */ + return capability_obj_p; +} /* ecma_promise_new_capability */ + +/** + * The common function for 'reject' and 'resolve'. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */ + ecma_value_t value, /**< rejected or resolved value */ + bool is_resolve) /**< the operation is resolve */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + if (is_resolve && ecma_is_value_object (value) && ecma_is_promise (ecma_get_object_from_value (value))) + { + ecma_object_t *object_p = ecma_get_object_from_value (value); + ecma_value_t constructor = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_CONSTRUCTOR); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return constructor; + } + + /* The this_arg must be an object. */ + bool is_same_value = (constructor == this_arg); + ecma_free_value (constructor); + + if (is_same_value) + { + return ecma_copy_value (value); + } + } + + ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg, ECMA_VALUE_UNDEFINED); + + if (JERRY_UNLIKELY (capability_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + + ecma_value_t func = is_resolve ? capability_p->resolve : capability_p->reject; + + ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func), ECMA_VALUE_UNDEFINED, &value, 1); + + if (ECMA_IS_VALUE_ERROR (call_ret)) + { + ecma_deref_object (capability_obj_p); + return call_ret; + } + + ecma_free_value (call_ret); + + ecma_value_t promise = ecma_copy_value (capability_p->header.u.cls.u3.promise); + ecma_deref_object (capability_obj_p); + + return promise; +} /* ecma_promise_reject_or_resolve */ + +/** + * The common function for ecma_builtin_promise_prototype_then + * and ecma_builtin_promise_prototype_catch. + * + * @return ecma value of a new promise object. + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_promise_then (ecma_value_t promise, /**< the promise which call 'then' */ + ecma_value_t on_fulfilled, /**< on_fulfilled function */ + ecma_value_t on_rejected) /**< on_rejected function */ +{ + if (!ecma_is_value_object (promise)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj = ecma_get_object_from_value (promise); + + if (!ecma_is_promise (obj)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_PROMISE); + } + + ecma_value_t species = ecma_op_species_constructor (obj, ECMA_BUILTIN_ID_PROMISE); + if (ECMA_IS_VALUE_ERROR (species)) + { + return species; + } + + ecma_object_t *result_capability_obj_p = ecma_promise_new_capability (species, promise); + ecma_free_value (species); + + if (JERRY_UNLIKELY (result_capability_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t ret = ecma_promise_perform_then (promise, on_fulfilled, on_rejected, result_capability_obj_p); + ecma_deref_object (result_capability_obj_p); + + return ret; +} /* ecma_promise_then */ + +/** + * Definition of valueThunk function + * + * See also: + * ES2020 25.6.5.3.1 step 8. + * + * @return ecma value + */ +ecma_value_t +ecma_value_thunk_helper_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED_2 (args_p, args_count); + + ecma_promise_value_thunk_t *value_thunk_obj_p = (ecma_promise_value_thunk_t *) function_obj_p; + + return ecma_copy_value (value_thunk_obj_p->value); +} /* ecma_value_thunk_helper_cb */ + +/** + * Definition of thrower function + * + * See also: + * ES2020 25.6.5.3.2 step 8. + * + * @return ecma value + */ +ecma_value_t +ecma_value_thunk_thrower_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED_2 (args_p, args_count); + + ecma_promise_value_thunk_t *value_thunk_obj_p = (ecma_promise_value_thunk_t *) function_obj_p; + + jcontext_raise_exception (ecma_copy_value (value_thunk_obj_p->value)); + + return ECMA_VALUE_ERROR; +} /* ecma_value_thunk_thrower_cb */ + +/** + * Helper function for Then Finally and Catch Finally common parts + * + * See also: + * ES2020 25.6.5.3.1 + * ES2020 25.6.5.3.2 + * + * @return ecma value + */ +static ecma_value_t +ecma_promise_then_catch_finally_helper (ecma_object_t *function_obj_p, /**< function object */ + ecma_native_handler_id_t id, /**< handler id */ + ecma_value_t arg) /**< callback function argument */ +{ + /* 2. */ + ecma_promise_finally_function_t *finally_func_obj = (ecma_promise_finally_function_t *) function_obj_p; + + /* 3. */ + JERRY_ASSERT (ecma_op_is_callable (finally_func_obj->on_finally)); + + /* 4. */ + ecma_value_t result = + ecma_op_function_call (ecma_get_object_from_value (finally_func_obj->on_finally), ECMA_VALUE_UNDEFINED, NULL, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + /* 6. */ + JERRY_ASSERT (ecma_is_constructor (finally_func_obj->constructor)); + + /* 7. */ + ecma_value_t promise = ecma_promise_reject_or_resolve (finally_func_obj->constructor, result, true); + + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (promise)) + { + return promise; + } + + /* 8. */ + ecma_object_t *value_thunk_func_p; + value_thunk_func_p = ecma_op_create_native_handler (id, sizeof (ecma_promise_value_thunk_t)); + + ecma_promise_value_thunk_t *value_thunk_func_obj = (ecma_promise_value_thunk_t *) value_thunk_func_p; + value_thunk_func_obj->value = ecma_copy_value_if_not_object (arg); + + /* 9. */ + ecma_value_t value_thunk = ecma_make_object_value (value_thunk_func_p); + ecma_value_t ret_value = ecma_op_invoke_by_magic_id (promise, LIT_MAGIC_STRING_THEN, &value_thunk, 1); + + ecma_free_value (promise); + ecma_deref_object (value_thunk_func_p); + + return ret_value; +} /* ecma_promise_then_catch_finally_helper */ + +/** + * Definition of Then Finally Function + * + * See also: + * ES2020 25.6.5.3.1 + * + * @return ecma value + */ +ecma_value_t +ecma_promise_then_finally_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED (args_count); + JERRY_ASSERT (args_count > 0); + + return ecma_promise_then_catch_finally_helper (function_obj_p, ECMA_NATIVE_HANDLER_VALUE_THUNK, args_p[0]); +} /* ecma_promise_then_finally_cb */ + +/** + * Definition of Catch Finally Function + * + * See also: + * ES2020 25.6.5.3.2 + * + * @return ecma value + */ +ecma_value_t +ecma_promise_catch_finally_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED (args_count); + JERRY_ASSERT (args_count > 0); + + return ecma_promise_then_catch_finally_helper (function_obj_p, ECMA_NATIVE_HANDLER_VALUE_THROWER, args_p[0]); +} /* ecma_promise_catch_finally_cb */ + +/** + * The common function for ecma_builtin_promise_prototype_finally + * + * @return ecma value of a new promise object. + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_promise_finally (ecma_value_t promise, /**< the promise which call 'finally' */ + ecma_value_t on_finally) /**< on_finally function */ +{ + /* 2. */ + if (!ecma_is_value_object (promise)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_object_t *obj = ecma_get_object_from_value (promise); + + /* 3. */ + ecma_value_t species = ecma_op_species_constructor (obj, ECMA_BUILTIN_ID_PROMISE); + + if (ECMA_IS_VALUE_ERROR (species)) + { + return species; + } + + /* 4. */ + JERRY_ASSERT (ecma_is_constructor (species)); + + /* 5. */ + if (!ecma_op_is_callable (on_finally)) + { + ecma_free_value (species); + ecma_value_t invoke_args[2] = { on_finally, on_finally }; + return ecma_op_invoke_by_magic_id (promise, LIT_MAGIC_STRING_THEN, invoke_args, 2); + } + + /* 6.a-b */ + ecma_object_t *then_finally_obj_p; + then_finally_obj_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY, sizeof (ecma_promise_finally_function_t)); + + /* 6.c-d */ + ecma_promise_finally_function_t *then_finally_func_obj_p = (ecma_promise_finally_function_t *) then_finally_obj_p; + then_finally_func_obj_p->constructor = species; + then_finally_func_obj_p->on_finally = on_finally; + + /* 6.e-f */ + ecma_object_t *catch_finally_obj_p; + catch_finally_obj_p = + ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY, sizeof (ecma_promise_finally_function_t)); + + /* 6.g-h */ + ecma_promise_finally_function_t *catch_finally_func_obj = (ecma_promise_finally_function_t *) catch_finally_obj_p; + catch_finally_func_obj->constructor = species; + catch_finally_func_obj->on_finally = on_finally; + + ecma_deref_object (ecma_get_object_from_value (species)); + + /* 7. */ + ecma_value_t invoke_args[2] = { ecma_make_object_value (then_finally_obj_p), + ecma_make_object_value (catch_finally_obj_p) }; + + ecma_value_t ret_value = ecma_op_invoke_by_magic_id (promise, LIT_MAGIC_STRING_THEN, invoke_args, 2); + + ecma_deref_object (then_finally_obj_p); + ecma_deref_object (catch_finally_obj_p); + + return ret_value; +} /* ecma_promise_finally */ + +/** + * Resume the execution of an async function after the promise is resolved + */ +void +ecma_promise_async_then (ecma_value_t promise, /**< promise object */ + ecma_value_t executable_object) /**< executable object of the async function */ +{ + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + uint16_t flags = ecma_promise_get_flags (promise_obj_p); + + if (flags & ECMA_PROMISE_IS_PENDING) + { + ecma_value_t executable_object_with_tag; + ECMA_SET_NON_NULL_POINTER_TAG (executable_object_with_tag, ecma_get_object_from_value (executable_object), 0); + ECMA_SET_THIRD_BIT_TO_POINTER_TAG (executable_object_with_tag); + + ecma_collection_push_back (((ecma_promise_object_t *) promise_obj_p)->reactions, executable_object_with_tag); + return; + } + + ecma_value_t value = ecma_promise_get_result (promise_obj_p); + ecma_enqueue_promise_async_reaction_job (executable_object, value, !(flags & ECMA_PROMISE_IS_FULFILLED)); + ecma_free_value (value); + +} /* ecma_promise_async_then */ + +/** + * Resolves the value and resume the execution of an async function after the resolve is completed + * + * @return ECMA_VALUE_UNDEFINED if not error is occurred, an error otherwise + */ +ecma_value_t +ecma_promise_async_await (ecma_extended_object_t *async_generator_object_p, /**< async generator function */ + ecma_value_t value) /**< value to be resolved (takes the reference) */ +{ + ecma_value_t promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE)); + ecma_value_t result = ecma_promise_reject_or_resolve (promise, value, true); + + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_promise_async_then (result, ecma_make_object_value ((ecma_object_t *) async_generator_object_p)); + ecma_free_value (result); + return ECMA_VALUE_UNDEFINED; +} /* ecma_promise_async_await */ + +/** + * Reject the promise if the value is error. + * + * See also: + * ES2015 25.4.1.1.1 + * + * @return ecma value of the new promise. + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_if_abrupt_reject_promise (ecma_value_t *value_p, /**< [in - out] completion value */ + ecma_object_t *capability_obj_p) /**< capability */ +{ + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + + if (!ECMA_IS_VALUE_ERROR (*value_p)) + { + return ECMA_VALUE_EMPTY; + } + + ecma_value_t reason = jcontext_take_exception (); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + ecma_value_t call_ret = + ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &reason, 1); + ecma_free_value (reason); + + if (ECMA_IS_VALUE_ERROR (call_ret)) + { + *value_p = call_ret; + return call_ret; + } + + ecma_free_value (call_ret); + *value_p = ecma_copy_value (capability_p->header.u.cls.u3.promise); + + return ECMA_VALUE_EMPTY; +} /* ecma_op_if_abrupt_reject_promise */ + +/** + * It performs the "then" operation on promiFulfilled + * and onRejected as its settlement actions. + * + * See also: 25.4.5.3.1 + * + * @return ecma value of the new promise object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_promise_perform_then (ecma_value_t promise, /**< the promise which call 'then' */ + ecma_value_t on_fulfilled, /**< on_fulfilled function */ + ecma_value_t on_rejected, /**< on_rejected function */ + ecma_object_t *result_capability_obj_p) /**< promise capability */ +{ + JERRY_ASSERT (ecma_object_class_is (result_capability_obj_p, ECMA_OBJECT_CLASS_PROMISE_CAPABILITY)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) result_capability_obj_p; + + /* 3. boolean true indicates "indentity" */ + if (!ecma_op_is_callable (on_fulfilled)) + { + on_fulfilled = ECMA_VALUE_TRUE; + } + + /* 4. boolean false indicates "thrower" */ + if (!ecma_op_is_callable (on_rejected)) + { + on_rejected = ECMA_VALUE_FALSE; + } + + ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise); + ecma_promise_object_t *promise_p = (ecma_promise_object_t *) promise_obj_p; + + uint16_t flags = ecma_promise_get_flags (promise_obj_p); + + if (flags & ECMA_PROMISE_IS_PENDING) + { + /* 7. */ + /* [ capability, (on_fulfilled), (on_rejected) ] */ + ecma_value_t reaction_values[3]; + ecma_value_t *reactions_p = reaction_values + 1; + + uint8_t tag = 0; + + if (on_fulfilled != ECMA_VALUE_TRUE) + { + tag |= JMEM_FIRST_TAG_BIT_MASK; + *reactions_p++ = on_fulfilled; + } + + if (on_rejected != ECMA_VALUE_FALSE) + { + tag |= JMEM_SECOND_TAG_BIT_MASK; + *reactions_p++ = on_rejected; + } + + ECMA_SET_NON_NULL_POINTER_TAG (reaction_values[0], result_capability_obj_p, tag); + + uint32_t value_count = (uint32_t) (reactions_p - reaction_values); + ecma_collection_append (promise_p->reactions, reaction_values, value_count); + } + else if (flags & ECMA_PROMISE_IS_FULFILLED) + { + /* 8. */ + ecma_value_t value = ecma_promise_get_result (promise_obj_p); + ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_fulfilled, value); + ecma_free_value (value); + } + else + { + /* 9. */ + ecma_value_t reason = ecma_promise_get_result (promise_obj_p); + ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_rejected, reason); + ecma_free_value (reason); + } + + /* 10. */ + return ecma_copy_value (capability_p->header.u.cls.u3.promise); +} /* ecma_promise_perform_then */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.h new file mode 100644 index 00000000..8cfaa454 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-promise-object.h @@ -0,0 +1,146 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_PROMISE_OBJECT_H +#define ECMA_PROMISE_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaarraybufferobject ECMA ArrayBuffer object related routines + * @{ + */ + +/** + * The PromiseState of promise object. + */ +typedef enum +{ + ECMA_PROMISE_IS_PENDING = (1 << 0), /**< pending state */ + ECMA_PROMISE_IS_FULFILLED = (1 << 1), /**< fulfilled state */ + ECMA_PROMISE_ALREADY_RESOLVED = (1 << 2), /**< already resolved */ +#if JERRY_PROMISE_CALLBACK + ECMA_PROMISE_UNHANDLED_REJECT = (1 << 3), /**< a Promise is rejected without a catch handler, + * related to ES11: 25.6.6 [[PromiseIsHandled]] */ +#endif /* JERRY_PROMISE_CALLBACK */ +} ecma_promise_flags_t; + +/** + * Description of a promise resolving function. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t promise; /**< [[Promise]] internal slot */ +} ecma_promise_resolver_t; + +/** + * Description of the promise object. + * It need more space than normal object to store builtin properties. + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_collection_t *reactions; /**< list of promise reactions */ +} ecma_promise_object_t; + +/** + * Description of the finally function object + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t constructor; /**< [[Constructor]] internal slot */ + ecma_value_t on_finally; /**< [[OnFinally]] internal slot */ +} ecma_promise_finally_function_t; + +/** + * Description of the thunk function object + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t value; /**< value thunk */ +} ecma_promise_value_thunk_t; + +/* The Promise reaction is a compressed structure, where each item can + * be a sequence of up to three ecma object values as seen below: + * + * [ Capability ][ Optional fullfilled callback ][ Optional rejected callback ] + * [ Async function callback ] + * + * The first member is an object, which lower bits specify the type of the reaction: + * bit 2 is not set: callback reactions + * The first two objects specify the resolve/reject functions of the promise + * returned by the `then` operation which can be used to chain event handlers. + * + * bit 0: has a fullfilled callback + * bit 1: has a rejected callback + * + * bit 2 is set: async function callback + */ + +bool ecma_is_promise (ecma_object_t *obj_p); +ecma_value_t ecma_op_create_promise_object (ecma_value_t executor, ecma_value_t parent, ecma_object_t *new_target_p); +uint8_t ecma_promise_get_flags (ecma_object_t *promise_p); +ecma_value_t ecma_promise_get_result (ecma_object_t *promise_p); +void ecma_reject_promise (ecma_value_t promise, ecma_value_t reason); +void ecma_fulfill_promise (ecma_value_t promise, ecma_value_t value); +ecma_value_t ecma_reject_promise_with_checks (ecma_value_t promise, ecma_value_t reason); +ecma_value_t ecma_fulfill_promise_with_checks (ecma_value_t promise, ecma_value_t value); +ecma_object_t *ecma_promise_new_capability (ecma_value_t constructor, ecma_value_t parent); +ecma_value_t ecma_promise_reject_or_resolve (ecma_value_t this_arg, ecma_value_t value, bool is_resolve); +ecma_value_t ecma_promise_then (ecma_value_t promise, ecma_value_t on_fulfilled, ecma_value_t on_rejected); + +ecma_value_t +ecma_value_thunk_helper_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_value_thunk_thrower_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_promise_then_finally_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_promise_catch_finally_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); +ecma_value_t +ecma_promise_reject_handler (ecma_object_t *function_obj_p, const ecma_value_t argv[], const uint32_t args_count); +ecma_value_t +ecma_promise_resolve_handler (ecma_object_t *function_obj_p, const ecma_value_t argv[], const uint32_t args_count); +ecma_value_t ecma_promise_all_or_all_settled_handler_cb (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); +ecma_value_t ecma_op_get_capabilities_executor_cb (ecma_object_t *function_obj_p, + const ecma_value_t args_p[], + const uint32_t args_count); + +ecma_value_t ecma_promise_finally (ecma_value_t promise, ecma_value_t on_finally); +void ecma_promise_async_then (ecma_value_t promise, ecma_value_t executable_object); +ecma_value_t ecma_promise_async_await (ecma_extended_object_t *async_generator_object_p, ecma_value_t value); +ecma_value_t ecma_promise_run_executor (ecma_object_t *promise_p, ecma_value_t executor, ecma_value_t this_value); +ecma_value_t ecma_op_if_abrupt_reject_promise (ecma_value_t *value_p, ecma_object_t *capability_obj_p); + +uint32_t ecma_promise_remaining_inc_or_dec (ecma_value_t remaining, bool is_inc); + +ecma_value_t ecma_promise_perform_then (ecma_value_t promise, + ecma_value_t on_fulfilled, + ecma_value_t on_rejected, + ecma_object_t *result_capability_obj_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_PROMISE_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.cpp new file mode 100644 index 00000000..35ff2bf0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.cpp @@ -0,0 +1,1875 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-proxy-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-handlers.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaproxyobject ECMA Proxy object related routines + * @{ + */ + +#if JERRY_BUILTIN_PROXY +/** + * ProxyCreate operation for create a new proxy object + * + * See also: + * ES2015 9.5.15 + * ES11+: 9.5.14 ProxyCreate + * + * @return created Proxy object as an ecma-value - if success + * raised error - otherwise + */ +ecma_object_t * +ecma_proxy_create (ecma_value_t target, /**< proxy target */ + ecma_value_t handler, /**< proxy handler */ + uint32_t options) /**< ecma_proxy_flag_types_t option bits */ +{ + /* ES2015: 1, 3. */ + /* ES11+: 1 - 2. */ + if (!ecma_is_value_object (target) || !ecma_is_value_object (handler)) + { + ecma_raise_type_error (ECMA_ERR_CANNOT_CREATE_PROXY); + return NULL; + } + + /* ES2015: 5 - 6. */ + /* ES11+: 3 - 4. */ + /* A Proxy does not have [[Prototype]] value as per standard */ + ecma_object_t *obj_p = ecma_create_object (NULL, sizeof (ecma_proxy_object_t), ECMA_OBJECT_TYPE_PROXY); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + obj_p->u2.prototype_cp = (jmem_cpointer_t) options; + + /* ES2015: 7. */ + /* ES11+: 5. */ + if (ecma_op_is_callable (target)) + { + obj_p->u2.prototype_cp |= ECMA_PROXY_IS_CALLABLE; + + /* ES2015: 7.b. */ + /* ES11+: 5.b. */ + if (ecma_is_constructor (target)) + { + obj_p->u2.prototype_cp |= ECMA_PROXY_IS_CONSTRUCTABLE; + } + } + + /* ES2015: 8. */ + /* ES11+: 6. */ + proxy_obj_p->target = target; + + /* ES2015: 9. */ + /* ES11+: 7. */ + proxy_obj_p->handler = handler; + + /* ES2015: 10. */ + /* ES11+: 8 */ + return obj_p; +} /* ecma_proxy_create */ + +/** + * Definition of Proxy Revocation Function + * + * See also: + * ES2015 26.2.2.1.1 + * + * @return ECMA_VALUE_UNDEFINED + */ +ecma_value_t +ecma_proxy_revoke_cb (ecma_object_t *function_obj_p, /**< function object */ + const ecma_value_t args_p[], /**< argument list */ + const uint32_t args_count) /**< argument number */ +{ + JERRY_UNUSED_2 (args_p, args_count); + + /* 1. */ + ecma_revocable_proxy_object_t *rev_proxy_p = (ecma_revocable_proxy_object_t *) function_obj_p; + + /* 2. */ + if (ecma_is_value_null (rev_proxy_p->proxy)) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 4. */ + ecma_proxy_object_t *proxy_p = (ecma_proxy_object_t *) ecma_get_object_from_value (rev_proxy_p->proxy); + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY ((ecma_object_t *) proxy_p)); + + /* 3. */ + rev_proxy_p->proxy = ECMA_VALUE_NULL; + + /* 5. */ + proxy_p->target = ECMA_VALUE_NULL; + + /* 6. */ + proxy_p->handler = ECMA_VALUE_NULL; + + /* 7. */ + return ECMA_VALUE_UNDEFINED; +} /* ecma_proxy_revoke_cb */ + +/** + * Proxy.revocable operation for create a new revocable proxy object + * + * See also: + * ES2015 26.2.2.1 + * + * @return NULL - if the operation fails + * pointer to the newly created revocable proxy object - otherwise + */ +ecma_object_t * +ecma_proxy_create_revocable (ecma_value_t target, /**< target argument */ + ecma_value_t handler) /**< handler argument */ +{ + /* 1. */ + ecma_object_t *proxy_p = ecma_proxy_create (target, handler, 0); + + /* 2. */ + if (proxy_p == NULL) + { + return proxy_p; + } + + ecma_value_t proxy_value = ecma_make_object_value (proxy_p); + + /* 3. */ + ecma_object_t *func_obj_p; + func_obj_p = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROXY_REVOKE, sizeof (ecma_revocable_proxy_object_t)); + + /* 4. */ + ecma_revocable_proxy_object_t *rev_proxy_p = (ecma_revocable_proxy_object_t *) func_obj_p; + rev_proxy_p->proxy = proxy_value; + + ecma_property_value_t *prop_value_p; + ecma_value_t revoker = ecma_make_object_value (func_obj_p); + + /* 5. */ + ecma_object_t *obj_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + + /* 6. */ + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROXY), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = proxy_value; + + /* 7. */ + prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_REVOKE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = revoker; + + ecma_deref_object (proxy_p); + ecma_deref_object (func_obj_p); + + /* 8. */ + return obj_p; +} /* ecma_proxy_create_revocable */ + +/** + * Internal find property operation for Proxy object + * + * Note: Returned value must be freed with ecma_free_value. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_NOT_FOUND - if the property is not found + * value of the property - otherwise + */ +ecma_value_t +ecma_proxy_object_find (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p) /**< property name */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + + ecma_value_t has_result = ecma_proxy_object_has (obj_p, prop_name_p); + + if (ECMA_IS_VALUE_ERROR (has_result)) + { + return has_result; + } + + if (ecma_is_value_false (has_result)) + { + return ECMA_VALUE_NOT_FOUND; + } + + return ecma_proxy_object_get (obj_p, prop_name_p, ecma_make_object_value (obj_p)); +} /* ecma_proxy_object_find */ + +/** + * Helper method for validate the proxy object + * + * @return proxy trap - if the validation is successful + * ECMA_VALUE_ERROR - otherwise + */ +static ecma_value_t +ecma_validate_proxy_object (ecma_value_t handler, /**< proxy handler */ + lit_magic_string_id_t magic_id) /**< routine magic id */ +{ + if (ecma_is_value_null (handler)) + { + return ecma_raise_type_error (ECMA_ERR_HANDLER_CANNOT_BE_NULL); + } + + JERRY_ASSERT (ecma_is_value_object (handler)); + + return ecma_op_get_method_by_magic_id (handler, magic_id); +} /* ecma_validate_proxy_object */ + +/* Interal operations */ + +/** + * The Proxy object [[GetPrototypeOf]] internal routine + * + * See also: + * ECMAScript v6, 9.5.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_NULL or valid object (prototype) otherwise + */ +ecma_value_t +ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_builtin_object_object_get_prototype_of (target_obj_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 8. */ + ecma_value_t handler_proto = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (handler_proto)) + { + return handler_proto; + } + + /* 10. */ + if (!ecma_is_value_object (handler_proto) && !ecma_is_value_null (handler_proto)) + { + ecma_free_value (handler_proto); + + return ecma_raise_type_error (ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL); + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return handler_proto; + } + + /* 11. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* 12. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + ecma_free_value (handler_proto); + + return extensible_target; + } + + /* 13. */ + if (ecma_is_value_true (extensible_target)) + { + return handler_proto; + } + + /* 14. */ + ecma_value_t target_proto = ecma_builtin_object_object_get_prototype_of (target_obj_p); + + /* 15. */ + if (ECMA_IS_VALUE_ERROR (target_proto)) + { + return target_proto; + } + + ecma_value_t ret_value = handler_proto; + + /* 16. */ + if (handler_proto != target_proto) + { + ecma_free_value (handler_proto); + + ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE); + } + + ecma_free_value (target_proto); + + /* 17. */ + return ret_value; +} /* ecma_proxy_object_get_prototype_of */ + +/** + * The Proxy object [[SetPrototypeOf]] internal routine + * + * See also: + * ECMAScript v6, 9.5.2 + * ECMAScript v11: 9.5.2 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the new prototype can be set for the given object + */ +ecma_value_t +ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, /**< proxy object */ + ecma_value_t proto) /**< new prototype object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (proto) || ecma_is_value_null (proto)); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL); + + /* 7.*/ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + if (ECMA_OBJECT_IS_PROXY (target_obj_p)) + { + ecma_value_t result = ecma_proxy_object_set_prototype_of (target_obj_p, proto); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_value_t result = ecma_op_ordinary_object_set_prototype_of (target_obj_p, proto); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t args[] = { target, proto }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* ES11: 9 */ + if (!boolean_trap_result) + { + return ecma_make_boolean_value (false); + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ecma_make_boolean_value (boolean_trap_result); + } + + /* 11. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* 12. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + return extensible_target; + } + + /* 13. */ + if (ecma_is_value_true (extensible_target)) + { + return ecma_make_boolean_value (boolean_trap_result); + } + + /* 14. */ + ecma_value_t target_proto = ecma_builtin_object_object_get_prototype_of (target_obj_p); + + /* 15. */ + if (ECMA_IS_VALUE_ERROR (target_proto)) + { + return target_proto; + } + + ecma_value_t ret_value = ecma_make_boolean_value (boolean_trap_result); + + /* 16. */ + if (boolean_trap_result && (target_proto != proto)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED); + } + + ecma_free_value (target_proto); + + /* 17. */ + return ret_value; +} /* ecma_proxy_object_set_prototype_of */ + +/** + * The Proxy object [[isExtensible]] internal routine + * + * See also: + * ECMAScript v6, 9.5.3 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the object is extensible + */ +ecma_value_t +ecma_proxy_object_is_extensible (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_IS_EXTENSIBLE); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_builtin_object_object_is_extensible (target_obj_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 8. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ecma_make_boolean_value (boolean_trap_result); + } + + bool target_result; + + /* 10. */ + if (ECMA_OBJECT_IS_PROXY (target_obj_p)) + { + ecma_value_t proxy_is_ext = ecma_proxy_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (proxy_is_ext)) + { + return proxy_is_ext; + } + + target_result = ecma_is_value_true (proxy_is_ext); + } + else + { + target_result = ecma_op_ordinary_object_is_extensible (target_obj_p); + } + + /* 12. */ + if (boolean_trap_result != target_result) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_EXTENSIBILITY); + } + + return ecma_make_boolean_value (boolean_trap_result); +} /* ecma_proxy_object_is_extensible */ + +/** + * The Proxy object [[PreventExtensions]] internal routine + * + * See also: + * ECMAScript v6, 9.5.4 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the object can be set as inextensible + */ +ecma_value_t +ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t ret_value = ecma_builtin_object_object_prevent_extensions (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + + ecma_deref_object (target_obj_p); + + return ECMA_VALUE_TRUE; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 8. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + /* 9. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 10. */ + if (boolean_trap_result && !(obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + ecma_value_t target_is_ext = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (target_is_ext)) + { + return target_is_ext; + } + + if (ecma_is_value_true (target_is_ext)) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_INEXTENSIBILITY); + } + } + + /* 11. */ + return ecma_make_boolean_value (boolean_trap_result); +} /* ecma_proxy_object_prevent_extensions */ + +/** + * The Proxy object [[GetOwnProperty]] internal routine + * + * See also: + * ECMAScript v6, 9.5.5 + * + * Note: - Returned value is always a simple value so freeing it is unnecessary. + * - If the operation does not fail, freeing the filled property descriptor is the caller's responsibility + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - depends on whether object has property with the given name + */ +ecma_value_t +ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + ecma_property_descriptor_t *prop_desc_p) /**< [out] property + * descriptor */ +{ + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL); + + ecma_value_t target = proxy_obj_p->target; + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, prop_desc_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_value }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + /* 11. */ + if (!ecma_is_value_object (trap_result) && !ecma_is_value_undefined (trap_result)) + { + ecma_free_value (trap_result); + return ecma_raise_type_error (ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED); + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + if (ecma_is_value_undefined (trap_result)) + { + return ECMA_VALUE_FALSE; + } + + ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, prop_desc_p); + ecma_free_value (trap_result); + + if (ECMA_IS_VALUE_ERROR (result_val)) + { + return result_val; + } + + ecma_op_to_complete_property_descriptor (prop_desc_p); + return ECMA_VALUE_TRUE; + } + + /* 12. */ + ecma_property_descriptor_t target_desc; + ecma_value_t target_status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 13. */ + if (ECMA_IS_VALUE_ERROR (target_status)) + { + ecma_free_value (trap_result); + return target_status; + } + + /* 14. */ + if (ecma_is_value_undefined (trap_result)) + { + /* .a */ + if (ecma_is_value_false (target_status)) + { + return ECMA_VALUE_FALSE; + } + /* .b */ + if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ecma_free_property_descriptor (&target_desc); + return ecma_raise_type_error (ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE); + } + + /* .c */ + ecma_free_property_descriptor (&target_desc); + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* .d */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + return extensible_target; + } + + /* .e */ + JERRY_ASSERT (ecma_is_value_boolean (extensible_target)); + + /* .f */ + if (ecma_is_value_false (extensible_target)) + { + return ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE); + } + + /* .g */ + return ECMA_VALUE_FALSE; + } + + /* 15. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + /* 16. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + if (ecma_is_value_true (target_status)) + { + ecma_free_property_descriptor (&target_desc); + } + ecma_free_value (trap_result); + return extensible_target; + } + + /* 17, 19 */ + ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, prop_desc_p); + + ecma_op_to_complete_property_descriptor (prop_desc_p); + ecma_free_value (trap_result); + + /* 18. */ + if (ECMA_IS_VALUE_ERROR (result_val)) + { + if (ecma_is_value_true (target_status)) + { + ecma_free_property_descriptor (&target_desc); + } + return result_val; + } + + /* 20. */ + bool is_extensible = ecma_is_value_true (extensible_target); + + bool is_valid = ecma_op_is_compatible_property_descriptor (prop_desc_p, + (ecma_is_value_true (target_status) ? &target_desc : NULL), + is_extensible); + + bool target_has_desc = ecma_is_value_true (target_status); + bool target_is_writable = (target_desc.flags & JERRY_PROP_IS_WRITABLE); + bool target_is_configurable = false; + + if (target_has_desc) + { + target_is_configurable = ((target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) != 0); + ecma_free_property_descriptor (&target_desc); + } + + /* 21. */ + if (!is_valid) + { + ecma_free_property_descriptor (prop_desc_p); + return ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + } + + /* 22. */ + else if (!(prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + { + const uint16_t mask = (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE); + + if (!target_has_desc || target_is_configurable + || ((prop_desc_p->flags & mask) == JERRY_PROP_IS_WRITABLE_DEFINED && target_is_writable)) + { + ecma_free_property_descriptor (prop_desc_p); + return ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + } + } + return ECMA_VALUE_TRUE; +} /* ecma_proxy_object_get_own_property_descriptor */ + +/** + * The Proxy object [[DefineOwnProperty]] internal routine + * + * See also: + * ECMAScript v6, 9.5.6 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - depends on whether the property can be defined for the given object + */ +ecma_value_t +ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_DEFINE_PROPERTY_UL); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_define_own_property (target_obj_p, prop_name_p, prop_desc_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + /* 9. */ + ecma_object_t *desc_obj = ecma_op_from_property_descriptor (prop_desc_p); + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t desc_obj_value = ecma_make_object_value (desc_obj); + ecma_value_t args[] = { target, prop_value, desc_obj_value }; + + /* 10. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 3); + + ecma_deref_object (func_obj_p); + ecma_deref_object (desc_obj); + + /* 11. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 12. */ + if (!boolean_trap_result) + { + return ECMA_VALUE_FALSE; + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ECMA_VALUE_TRUE; + } + + /* 13. */ + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 14. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + bool target_prop_found = ecma_is_value_true (status); + + /* 15. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + bool is_target_ext = ecma_is_value_true (extensible_target); + + /* 16. */ + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + if (target_prop_found) + { + ecma_free_property_descriptor (&target_desc); + } + + return extensible_target; + } + + /* 17. */ + bool setting_config_false = + ((prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) && !(prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + + /* 19. */ + if (!target_prop_found) + { + if (!is_target_ext) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET); + } + + if (setting_config_false) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); + } + } + /* 20. */ + else + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (!ecma_op_is_compatible_property_descriptor (prop_desc_p, &target_desc, is_target_ext)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_ADD_PROPERTY_INCOMPATIBLE_OTHER_PROP); + } + else if (setting_config_false && (target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); + } + /* ES11: 16.c */ + else if ((target_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) != 0 + && (prop_desc_p->flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + == JERRY_PROP_IS_WRITABLE_DEFINED + && (target_desc.flags & (JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_CONFIGURABLE)) == JERRY_PROP_IS_WRITABLE) + + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); + } + + ecma_free_property_descriptor (&target_desc); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + } + + return ECMA_VALUE_TRUE; +} /* ecma_proxy_object_define_own_property */ + +/** + * The Proxy object [[HasProperty]] internal routine + * + * See also: + * ECMAScript v6, 9.5.7 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - depends on whether the property is found + */ +ecma_value_t +ecma_proxy_object_has (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p) /**< property name */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_HAS); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_has_property (target_obj_p, prop_name_p); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_value }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 11. */ + if (!boolean_trap_result && !(obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + if (ecma_is_value_true (status)) + { + bool prop_is_configurable = target_desc.flags & JERRY_PROP_IS_CONFIGURABLE; + + ecma_free_property_descriptor (&target_desc); + + if (!prop_is_configurable) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_FALSISH_PROPERTY_NON_CONFIGURABLE); + } + + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + return extensible_target; + } + + if (ecma_is_value_false (extensible_target)) + { + return ecma_raise_type_error (ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE); + } + } + } + + /* 12. */ + return ecma_make_boolean_value (boolean_trap_result); +} /* ecma_proxy_object_has */ + +/** + * The Proxy object [[Get]] internal routine + * + * See also: + * ECMAScript v6, 9.5.8 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * value of the given nameddata property or the result of the getter function call - otherwise + */ +ecma_value_t +ecma_proxy_object_get (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver to invoke getter function */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_GET); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_object_t *target_obj_p = ecma_get_object_from_value (proxy_obj_p->target); + ecma_value_t result = ecma_op_object_get_with_receiver (target_obj_p, prop_name_p, receiver); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { proxy_obj_p->target, prop_value, receiver }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 3); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result) || (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + return trap_result; + } + + /* 11. */ + ecma_property_descriptor_t target_desc; + ecma_value_t status = ecma_op_get_own_property_descriptor (proxy_obj_p->target, prop_name_p, &target_desc); + + /* 12. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_free_value (trap_result); + return status; + } + + /* 13. */ + if (ecma_is_value_true (status)) + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if ((target_desc.flags & JERRY_PROP_IS_VALUE_DEFINED) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && !(target_desc.flags & JERRY_PROP_IS_WRITABLE) && !ecma_op_same_value (trap_result, target_desc.value)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP); + } + else if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && (target_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + && target_desc.get_p == NULL && !ecma_is_value_undefined (trap_result)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER); + } + + ecma_free_property_descriptor (&target_desc); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_free_value (trap_result); + + return ret_value; + } + } + + /* 14. */ + return trap_result; +} /* ecma_proxy_object_get */ + +/** + * The Proxy object [[Set]] internal routine + * + * See also: + * ECMAScript v6, 9.5.9 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the propety can be set to the given object + */ +ecma_value_t +ecma_proxy_object_set (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + ecma_value_t value, /**< value to set */ + ecma_value_t receiver, /**< receiver to invoke setter function */ + bool is_strict) /**< indicate strict mode */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_SET); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_put_with_receiver (target_obj_p, prop_name_p, value, receiver, is_strict); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_name_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_name_value, value, receiver }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 4); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 11. */ + if (!boolean_trap_result) + { + if (is_strict) + { + return ecma_raise_type_error (ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); + } + + return ECMA_VALUE_FALSE; + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ECMA_VALUE_TRUE; + } + + /* 12. */ + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 13. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + /* 14. */ + if (ecma_is_value_true (status)) + { + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if ((target_desc.flags & JERRY_PROP_IS_VALUE_DEFINED) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && !(target_desc.flags & JERRY_PROP_IS_WRITABLE) && !ecma_op_same_value (value, target_desc.value)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP); + } + else if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) + && (target_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + && target_desc.set_p == NULL) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER); + } + + ecma_free_property_descriptor (&target_desc); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + } + + /* 15. */ + return ECMA_VALUE_TRUE; +} /* ecma_proxy_object_set */ + +/** + * The Proxy object [[Delete]] internal routine + * + * See also: + * ECMAScript v6, 9.5.10 + * + * Note: Returned value is always a simple value so freeing it is unnecessary. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE/FALSE} - depends on whether the propety can be deleted + */ +ecma_value_t +ecma_proxy_object_delete_property (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p, /**< property name */ + bool is_strict) /**< delete in strict mode? */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 2. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 3-6.*/ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_DELETE_PROPERTY_UL); + + /* 7. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 8. */ + if (ecma_is_value_undefined (trap)) + { + ecma_value_t result = ecma_op_object_delete (target_obj_p, prop_name_p, is_strict); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t prop_name_value = ecma_make_prop_name_value (prop_name_p); + ecma_value_t args[] = { target, prop_name_value }; + + /* 9. */ + ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + + ecma_deref_object (func_obj_p); + + /* 10. */ + if (ECMA_IS_VALUE_ERROR (trap_result)) + { + return trap_result; + } + + bool boolean_trap_result = ecma_op_to_boolean (trap_result); + + ecma_free_value (trap_result); + + /* 11. */ + if (!boolean_trap_result) + { + return ECMA_VALUE_FALSE; + } + + if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) + { + return ECMA_VALUE_TRUE; + } + + /* 12. */ + ecma_property_descriptor_t target_desc; + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + /* 13. */ + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; + } + + /* 14. */ + if (ecma_is_value_false (status)) + { + return ECMA_VALUE_TRUE; + } + + ecma_value_t ret_value = ECMA_VALUE_TRUE; + + /* 15. */ + if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_PROPERTY_NON_CONFIGURABLE); + } + /* ES11: 13-14 */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (!ecma_is_value_true (extensible_target)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_TARGET_NOT_EXTENSIBLE); + } + + ecma_free_property_descriptor (&target_desc); + + /* 16. */ + return ret_value; +} /* ecma_proxy_object_delete_property */ + +/** + * Helper method for the Proxy object [[OwnPropertyKeys]] operation + * + * See also: + * ECMAScript v6, 9.5.12 steps 21. 23. + * + * @return ECMA_VALUE_ERROR - if a target key is not in the unchecked_result_keys collection + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_value_t +ecma_proxy_object_own_property_keys_helper (ecma_collection_t *target_collection, /**< target keys */ + ecma_collection_t *unchecked_result_keys, /**< unchecked keys */ + uint32_t *counter) /**< unchecked property counter */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + for (uint32_t i = 0; i < target_collection->item_count; i++) + { + ecma_string_t *current_prop_name = ecma_get_prop_name_from_value (target_collection->buffer_p[i]); + + ret_value = ECMA_VALUE_ERROR; + + for (uint32_t j = 0; j < unchecked_result_keys->item_count; j++) + { + if (ecma_is_value_empty (unchecked_result_keys->buffer_p[j])) + { + continue; + } + + ecma_string_t *unchecked_prop_name = ecma_get_prop_name_from_value (unchecked_result_keys->buffer_p[j]); + + if (ecma_compare_ecma_strings (current_prop_name, unchecked_prop_name)) + { + ecma_deref_ecma_string (unchecked_prop_name); + ret_value = ECMA_VALUE_EMPTY; + unchecked_result_keys->buffer_p[j] = ECMA_VALUE_EMPTY; + (*counter)++; + } + } + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + break; + } + } + + return ret_value; +} /* ecma_proxy_object_own_property_keys_helper */ + +/** + * Helper method for checking the invariants in the Proxy object [[OwnPropertyKeys]] operation + * + * See also: + * ECMAScript v6, 9.5.12 steps 20-25. + * + * @return true - if none of the invariants got violated + * false - otherwise + */ +static bool +ecma_proxy_check_invariants_for_own_prop_keys (ecma_collection_t *trap_result, + ecma_collection_t *target_non_configurable_keys, + ecma_collection_t *target_configurable_keys, + ecma_value_t extensible_target) +{ + /* 20. */ + ecma_collection_t *unchecked_result_keys = ecma_new_collection (); + + ecma_collection_append (unchecked_result_keys, trap_result->buffer_p, trap_result->item_count); + + for (uint32_t i = 0; i < unchecked_result_keys->item_count; i++) + { + ecma_string_t *unchecked_prop_name = ecma_get_prop_name_from_value (unchecked_result_keys->buffer_p[i]); + ecma_ref_ecma_string (unchecked_prop_name); + } + + bool check_ok = false; + uint32_t unchecked_prop_name_counter = 0; + + /* 21. */ + if (ECMA_IS_VALUE_ERROR (ecma_proxy_object_own_property_keys_helper (target_non_configurable_keys, + unchecked_result_keys, + &unchecked_prop_name_counter))) + { + ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_NON_CONFIGURABLE_KEYS); + } + /* 22. */ + else if (ecma_is_value_true (extensible_target)) + { + check_ok = true; + } + /* 23. */ + else if (ECMA_IS_VALUE_ERROR (ecma_proxy_object_own_property_keys_helper (target_configurable_keys, + unchecked_result_keys, + &unchecked_prop_name_counter))) + { + ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_CONFIGURABLE_KEYS); + } + /* 24. */ + else if (unchecked_result_keys->item_count != unchecked_prop_name_counter) + { + ecma_raise_type_error (ECMA_ERR_TRAP_EXTRA_KEYS_FOR_A_NON_EXTENSIBLE_TARGET); + } + /* 25. */ + else + { + check_ok = true; + } + + ecma_collection_free (unchecked_result_keys); + + return check_ok; +} /* ecma_proxy_check_invariants_for_own_prop_keys */ + +/** + * The Proxy object [[OwnPropertyKeys]] internal routine + * + * See also: + * ECMAScript v11, 9.5.11 + * + * Note: If the returned collection is not NULL, it must be freed with + * ecma_collection_free if it is no longer needed + * + * @return NULL - if the operation fails + * pointer to a newly allocated list of property names - otherwise + */ +ecma_collection_t * +ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE_RETURN (NULL); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_OWN_KEYS_UL); + + if (ECMA_IS_VALUE_ERROR (trap)) + { + return NULL; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 6. */ + if (ecma_is_value_undefined (trap)) + { + ecma_collection_t *result = ecma_op_object_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + + /* 7. */ + ecma_value_t trap_result_array = ecma_op_function_call (func_obj_p, handler, &target, 1); + + ecma_deref_object (func_obj_p); + + if (ECMA_IS_VALUE_ERROR (trap_result_array)) + { + return NULL; + } + + /* 8. */ + ecma_collection_t *trap_result = ecma_op_create_list_from_array_like (trap_result_array, true); + + ecma_free_value (trap_result_array); + + if (trap_result == NULL || (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) + { + return trap_result; + } + + /* 9. */ + if (ecma_collection_check_duplicated_entries (trap_result)) + { + ecma_collection_free (trap_result); + ecma_raise_type_error (ECMA_ERR_TRAP_WITH_DUPLICATED_ENTRIES); + return NULL; + } + + /* 10. */ + ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + + if (ECMA_IS_VALUE_ERROR (extensible_target)) + { + ecma_collection_free (trap_result); + return NULL; + } + + /* 11. */ + ecma_collection_t *target_keys = ecma_op_object_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); + + if (target_keys == NULL) + { + ecma_collection_free (trap_result); + return target_keys; + } + + /* 14. */ + ecma_collection_t *target_configurable_keys = ecma_new_collection (); + + /* 15. */ + ecma_collection_t *target_non_configurable_keys = ecma_new_collection (); + + ecma_collection_t *ret_value = NULL; + + /* 16. */ + for (uint32_t i = 0; i < target_keys->item_count; i++) + { + ecma_property_descriptor_t target_desc; + + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (target_keys->buffer_p[i]); + + ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_free (trap_result); + goto free_target_collections; + } + + ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); + + if (ecma_is_value_true (status) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + { + ecma_collection_push_back (target_non_configurable_keys, prop_value); + } + else + { + ecma_collection_push_back (target_configurable_keys, prop_value); + } + + if (ecma_is_value_true (status)) + { + ecma_free_property_descriptor (&target_desc); + } + } + + /* 17. */ + if (ecma_is_value_true (extensible_target) && target_non_configurable_keys->item_count == 0) + { + ret_value = trap_result; + } + /* 18-22. */ + else if (ecma_proxy_check_invariants_for_own_prop_keys (trap_result, + target_non_configurable_keys, + target_configurable_keys, + extensible_target)) + { + ret_value = trap_result; + } + else + { + JERRY_ASSERT (ret_value == NULL); + ecma_collection_free (trap_result); + } + +free_target_collections: + ecma_collection_destroy (target_keys); + ecma_collection_free (target_configurable_keys); + ecma_collection_free (target_non_configurable_keys); + + /* 23. */ + return ret_value; +} /* ecma_proxy_object_own_property_keys */ + +/** + * The Proxy object [[Call]] internal routine + * + * See also: + * ECMAScript v6, 9.5.13 + * + * Note: Returned value must be freed with ecma_free_value. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * result of the function call - otherwise + */ +ecma_value_t +ecma_proxy_object_call (ecma_object_t *obj_p, /**< proxy object */ + ecma_value_t this_argument, /**< this argument to invoke the function */ + const ecma_value_t *args_p, /**< argument list */ + uint32_t argc) /**< number of arguments */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + + if (!ecma_op_proxy_object_is_callable (obj_p)) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + } + + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5.*/ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_APPLY); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + ecma_value_t result = ecma_op_function_call (target_obj_p, this_argument, args_p, argc); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + /* 8. */ + ecma_value_t args_array = ecma_op_new_array_object_from_buffer (args_p, argc); + ecma_value_t value_array[] = { target, this_argument, args_array }; + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + /* 9. */ + ecma_value_t ret_value = ecma_op_function_call (func_obj_p, handler, value_array, 3); + ecma_deref_object (func_obj_p); + ecma_free_object (args_array); + + return ret_value; +} /* ecma_proxy_object_call */ + +/** + * The Proxy object [[Construct]] internal routine + * + * See also: + * ECMAScript v6, 9.5.14 + * + * Note: Returned value must be freed with ecma_free_value. + * + * @return ECMA_VALUE_ERROR - if the operation fails + * result of the construct call - otherwise + */ +ecma_value_t +ecma_proxy_object_construct (ecma_object_t *obj_p, /**< proxy object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *args_p, /**< argument list */ + uint32_t argc) /**< number of arguments */ +{ + JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); + ECMA_CHECK_STACK_USAGE (); + + ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; + + /* 1. */ + ecma_value_t handler = proxy_obj_p->handler; + + /* 2-5. */ + ecma_value_t trap = ecma_validate_proxy_object (handler, LIT_MAGIC_STRING_CONSTRUCT); + + /* 6. */ + if (ECMA_IS_VALUE_ERROR (trap)) + { + return trap; + } + + ecma_value_t target = proxy_obj_p->target; + ecma_object_t *target_obj_p = ecma_get_object_from_value (target); + + /* 7. */ + if (ecma_is_value_undefined (trap)) + { + JERRY_ASSERT (ecma_object_is_constructor (target_obj_p)); + + ecma_value_t result = ecma_op_function_construct (target_obj_p, new_target_p, args_p, argc); + JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); + return result; + } + + /* 8. */ + ecma_value_t args_array = ecma_op_new_array_object_from_buffer (args_p, argc); + + ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); + ecma_value_t new_target_value = ecma_make_object_value (new_target_p); + ecma_value_t function_call_args[] = { target, args_array, new_target_value }; + + /* 9. */ + ecma_value_t new_obj = ecma_op_function_call (func_obj_p, handler, function_call_args, 3); + + ecma_free_object (args_array); + ecma_deref_object (func_obj_p); + + /* 10 .*/ + if (ECMA_IS_VALUE_ERROR (new_obj)) + { + return new_obj; + } + + /* 11. */ + if (!ecma_is_value_object (new_obj)) + { + ecma_free_value (new_obj); + + return ecma_raise_type_error (ECMA_ERR_TRAP_MUST_RETURN_WITH_AN_OBJECT); + } + + /* 12. */ + return new_obj; +} /* ecma_proxy_object_construct */ + +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.h new file mode 100644 index 00000000..82537bca --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-proxy-object.h @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_PROXY_OBJECT_H +#define ECMA_PROXY_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaproxyobject ECMA Proxy object related routines + * @{ + */ + +#if JERRY_BUILTIN_PROXY + +ecma_object_t *ecma_proxy_create (ecma_value_t target, ecma_value_t handler, uint32_t options); + +ecma_object_t *ecma_proxy_create_revocable (ecma_value_t target, ecma_value_t handler); + +ecma_value_t +ecma_proxy_revoke_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); + +ecma_value_t ecma_proxy_object_find (ecma_object_t *obj_p, ecma_string_t *prop_name_p); + +/* Interal operations */ + +ecma_value_t ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_value_t ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, ecma_value_t proto); + +ecma_value_t ecma_proxy_object_is_extensible (ecma_object_t *obj_p); + +ecma_value_t ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p); + +ecma_value_t ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + ecma_property_descriptor_t *prop_desc_p); + +ecma_value_t ecma_proxy_object_define_own_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + const ecma_property_descriptor_t *prop_desc_p); + +ecma_value_t ecma_proxy_object_has (ecma_object_t *obj_p, ecma_string_t *prop_name_p); + +ecma_value_t ecma_proxy_object_get (ecma_object_t *obj_p, ecma_string_t *prop_name_p, ecma_value_t receiver); + +ecma_value_t ecma_proxy_object_set (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + ecma_value_t name, + ecma_value_t receiver, + bool is_strict); + +ecma_value_t ecma_proxy_object_delete_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p, bool is_strict); + +ecma_collection_t *ecma_proxy_object_own_property_keys (ecma_object_t *obj_p); + +ecma_value_t +ecma_proxy_object_call (ecma_object_t *obj_p, ecma_value_t this_argument, const ecma_value_t *args_p, uint32_t argc); + +ecma_value_t ecma_proxy_object_construct (ecma_object_t *obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *args_p, + uint32_t argc); + +#endif /* JERRY_BUILTIN_PROXY */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_PROXY_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.cpp new file mode 100644 index 00000000..bc8f3866 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.cpp @@ -0,0 +1,404 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-reference.h" + +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lcache.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" +#include "ecma-proxy-object.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup references ECMA-Reference + * @{ + */ + +/** + * Resolve syntactic reference. + * + * @return ECMA_OBJECT_POINTER_ERROR - if the operation fails + * pointer to lexical environment - if the reference's base is resolved successfully, + * NULL - otherwise. + */ +ecma_object_t * +ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical environment */ + ecma_string_t *name_p) /**< identifier's name */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + while (true) + { + ecma_value_t has_binding = ecma_op_has_binding (lex_env_p, name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (has_binding)) + { + return ECMA_OBJECT_POINTER_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (has_binding)) + { + return lex_env_p; + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + return NULL; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } +} /* ecma_op_resolve_reference_base */ + +/** + * Check if the passed lexical environment is a global lexical environment + * + * @return true - if the lexical environment is a global lexical environment + * false - otherwise + */ +static inline bool +ecma_op_is_global_environment (ecma_object_t *lex_env_p) /**< lexical environment */ +{ + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL + || (ecma_make_object_value (ecma_get_lex_env_binding_object (lex_env_p)) + == ((ecma_global_object_t *) ecma_builtin_get_global ())->this_binding)); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL + || ecma_get_lex_env_binding_object (lex_env_p) == ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + + return lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL; +} /* ecma_op_is_global_environment */ + +/** + * Perform GetThisEnvironment and GetSuperBase operations + * + * See also: ECMAScript v6, 8.1.1.3.5 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_UNDEFINED - if the home object is null + * value of the [[HomeObject]].[[Prototype]] internal slot - otherwise + */ +ecma_value_t +ecma_op_resolve_super_base (ecma_object_t *lex_env_p) /**< starting lexical environment */ +{ + while (true) + { + JERRY_ASSERT (lex_env_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && !ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_object_t *home_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u1.home_object_cp); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (home_p)) + { + return ecma_proxy_object_get_prototype_of (home_p); + } +#endif /* JERRY_BUILTIN_PROXY */ + + jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (home_p); + + if (proto_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_NULL; + } + + ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (proto_p); + + return ecma_make_object_value (proto_p); + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_resolve_super_base */ + +/** + * Helper method for HasBindig operation + * + * See also: + * ECMA-262 v6, 8.1.1.2.1 steps 7-9; + * + * @return ECMA_VALUE_TRUE - if the property is unscopable + * ECMA_VALUE_FALSE - if a the property is not unscopable + * ECMA_VALUE_ERROR - otherwise + */ +static ecma_value_t +ecma_op_is_prop_unscopable (ecma_object_t *binding_obj_p, /**< binding object */ + ecma_string_t *prop_name_p) /**< property's name */ +{ + ecma_value_t unscopables = ecma_op_object_get_by_symbol_id (binding_obj_p, LIT_GLOBAL_SYMBOL_UNSCOPABLES); + + if (ECMA_IS_VALUE_ERROR (unscopables)) + { + return unscopables; + } + + if (ecma_is_value_object (unscopables)) + { + ecma_object_t *unscopables_obj_p = ecma_get_object_from_value (unscopables); + ecma_value_t get_unscopables_value = ecma_op_object_get (unscopables_obj_p, prop_name_p); + ecma_deref_object (unscopables_obj_p); + + if (ECMA_IS_VALUE_ERROR (get_unscopables_value)) + { + return get_unscopables_value; + } + + bool is_blocked = ecma_op_to_boolean (get_unscopables_value); + + ecma_free_value (get_unscopables_value); + + return ecma_make_boolean_value (is_blocked); + } + + ecma_free_value (unscopables); + + return ECMA_VALUE_FALSE; +} /* ecma_op_is_prop_unscopable */ + +/** + * Helper method for HasBindig operation + * + * See also: + * ECMA-262 v6, 8.1.1.2.1 steps 7-9; + * + * @return ECMA_VALUE_TRUE - if the property is unscopable + * ECMA_VALUE_FALSE - if a the property is not unscopable + * ECMA_VALUE_ERROR - otherwise + */ + +/** + * Resolve value corresponding to the given object environment reference. + * + * Note: the steps are already include the HasBindig operation steps + * + * See also: + * ECMA-262 v6, 8.1.1.2.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_NOT_FOUND - if the binding not exists or blocked via @@unscopables + * result of the binding - otherwise + */ +ecma_value_t +ecma_op_object_bound_environment_resolve_reference_value (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p) /**< variable name */ +{ + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + ecma_value_t found_binding; + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + found_binding = ecma_proxy_object_has (binding_obj_p, name_p); + + if (!ecma_is_value_true (found_binding)) + { + return ECMA_IS_VALUE_ERROR (found_binding) ? found_binding : ECMA_VALUE_NOT_FOUND; + } + } + else + { +#endif /* JERRY_BUILTIN_PROXY */ + found_binding = ecma_op_object_find (binding_obj_p, name_p); + + if (ECMA_IS_VALUE_ERROR (found_binding) || !ecma_is_value_found (found_binding)) + { + return found_binding; + } + + if (JERRY_LIKELY (ecma_op_is_global_environment (lex_env_p))) + { + return found_binding; + } +#if JERRY_BUILTIN_PROXY + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_value_t blocked = ecma_op_is_prop_unscopable (binding_obj_p, name_p); + + if (ecma_is_value_false (blocked)) + { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + return ecma_proxy_object_get (binding_obj_p, name_p, ecma_make_object_value (binding_obj_p)); + } +#endif /* JERRY_BUILTIN_PROXY */ + return found_binding; + } + +#if JERRY_BUILTIN_PROXY + if (!ECMA_OBJECT_IS_PROXY (binding_obj_p)) + { + ecma_free_value (found_binding); + } +#endif /* JERRY_BUILTIN_PROXY */ + + return ECMA_IS_VALUE_ERROR (blocked) ? blocked : ECMA_VALUE_NOT_FOUND; +} /* ecma_op_object_bound_environment_resolve_reference_value */ + +/** + * Resolve value corresponding to reference. + * + * @return value of the reference + */ +ecma_value_t +ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ + ecma_string_t *name_p) /**< identifier's name */ +{ + JERRY_ASSERT (lex_env_p != NULL); + + while (true) + { + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p == NULL) + { + break; + } + + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } + case ECMA_LEXICAL_ENVIRONMENT_CLASS: + { +#if JERRY_MODULE_SYSTEM + if (ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p == NULL) + { + break; + } + + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + property_value_p = ecma_get_property_value_from_named_reference (property_value_p); + } + + if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + + return ecma_fast_copy_value (property_value_p->value); + } +#endif /* JERRY_MODULE_SYSTEM */ + break; + } + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + if (ecma_op_is_global_environment (lex_env_p)) + { +#if JERRY_LCACHE + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p); + + if (property_p != NULL) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { + return ecma_fast_copy_value (prop_value_p->value); + } + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + + ecma_value_t base_value = ecma_make_object_value (binding_obj_p); + return ecma_op_function_call (getter_p, base_value, NULL, 0); + } +#endif /* JERRY_LCACHE */ + } + + ecma_value_t result = ecma_op_object_bound_environment_resolve_reference_value (lex_env_p, name_p); + + if (ecma_is_value_found (result)) + { + /* Note: the result may contains ECMA_VALUE_ERROR */ + return result; + } + break; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + +#if JERRY_ERROR_MESSAGES + ecma_value_t name_val = ecma_make_string_value (name_p); + ecma_value_t error_value = + ecma_raise_standard_error_with_format (JERRY_ERROR_REFERENCE, "% is not defined", name_val); +#else /* JERRY_ERROR_MESSAGES */ + ecma_value_t error_value = ecma_raise_reference_error (ECMA_ERR_EMPTY); +#endif /* !JERRY_ERROR_MESSAGES */ + return error_value; +} /* ecma_op_resolve_reference_value */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.h new file mode 100644 index 00000000..e1d4ae79 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-reference.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_REFERENCE_H +#define ECMA_REFERENCE_H + +#include "ecma-globals.h" + +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup references ECMA-Reference + * @{ + */ + +ecma_object_t *ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_object_bound_environment_resolve_reference_value (ecma_object_t *lex_env_p, ecma_string_t *name_p); +ecma_value_t ecma_op_resolve_super_base (ecma_object_t *lex_env_p); + +/** + * @} + * @} + */ + +#endif /* !ECMA_REFERENCE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.cpp new file mode 100644 index 00000000..29fc9893 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.cpp @@ -0,0 +1,3219 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-regexp-object.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-objects.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "re-compiler.h" + +#if JERRY_BUILTIN_REGEXP + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaregexpobject ECMA RegExp object related routines + * @{ + */ + +/** + * Index of the global capturing group + */ +#define RE_GLOBAL_CAPTURE 0 + +/** + * Parse RegExp flags (global, ignoreCase, multiline) + * + * See also: ECMA-262 v5, 15.10.4.1 + * + * @return empty ecma value - if parsed successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_regexp_parse_flags (ecma_string_t *flags_str_p, /**< Input string with flags */ + uint16_t *flags_p) /**< [out] parsed flag bits */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + uint16_t result_flags = RE_FLAG_EMPTY; + + ECMA_STRING_TO_UTF8_STRING (flags_str_p, flags_start_p, flags_start_size); + + const lit_utf8_byte_t *flags_str_curr_p = flags_start_p; + const lit_utf8_byte_t *flags_str_end_p = flags_start_p + flags_start_size; + + while (flags_str_curr_p < flags_str_end_p) + { + ecma_regexp_flags_t flag; + switch (*flags_str_curr_p++) + { + case 'g': + { + flag = RE_FLAG_GLOBAL; + break; + } + case 'i': + { + flag = RE_FLAG_IGNORE_CASE; + break; + } + case 'm': + { + flag = RE_FLAG_MULTILINE; + break; + } + case 'y': + { + flag = RE_FLAG_STICKY; + break; + } + case 'u': + { + flag = RE_FLAG_UNICODE; + break; + } + case 's': + { + flag = RE_FLAG_DOTALL; + break; + } + default: + { + flag = RE_FLAG_EMPTY; + break; + } + } + + if (flag == RE_FLAG_EMPTY || (result_flags & flag) != 0) + { + ret_value = ecma_raise_syntax_error (ECMA_ERR_INVALID_REGEXP_FLAGS); + break; + } + + result_flags = (uint16_t) (result_flags | flag); + } + + ECMA_FINALIZE_UTF8_STRING (flags_start_p, flags_start_size); + + *flags_p = result_flags; + return ret_value; +} /* ecma_regexp_parse_flags */ + +/** + * RegExpAlloc method + * + * See also: ECMA-262 v5, 15.10.4.1 + * ECMA-262 v6, 21.2.3.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return ecma_object_t + */ +ecma_object_t * +ecma_op_regexp_alloc (ecma_object_t *ctr_obj_p) /**< constructor object pointer */ +{ + if (ctr_obj_p == NULL) + { + ctr_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP); + } + + ecma_object_t *proto_obj_p = ecma_op_get_prototype_from_constructor (ctr_obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_obj_p == NULL)) + { + return proto_obj_p; + } + + ecma_object_t *new_object_p = + ecma_create_object (proto_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_deref_object (proto_obj_p); + + ecma_extended_object_t *regexp_obj_p = (ecma_extended_object_t *) new_object_p; + + /* Class id will be initialized after the bytecode is compiled. */ + regexp_obj_p->u.cls.type = ECMA_OBJECT_CLASS__MAX; + + ecma_value_t status = ecma_builtin_helper_def_prop (new_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + ECMA_PROPERTY_FLAG_WRITABLE | JERRY_PROP_SHOULD_THROW); + + JERRY_ASSERT (ecma_is_value_true (status)); + + return new_object_p; +} /* ecma_op_regexp_alloc */ + +/** + * Helper method for initializing an aready existing RegExp object. + */ +static inline void +ecma_op_regexp_initialize (ecma_object_t *regexp_obj_p, /**< RegExp object */ + const re_compiled_code_t *bc_p) /**< bytecode */ +{ + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) regexp_obj_p; + ext_obj_p->u.cls.type = ECMA_OBJECT_CLASS_REGEXP; + ECMA_SET_INTERNAL_VALUE_POINTER (ext_obj_p->u.cls.u3.value, bc_p); +} /* ecma_op_regexp_initialize */ + +/** + * Method for creating a RegExp object from pattern. + * + * Note: + * Allocation have to happen before invoking this function using ecma_op_regexp_alloc. + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_regexp_from_pattern (ecma_object_t *regexp_obj_p, /**< RegExp object */ + ecma_value_t pattern_value, /**< pattern */ + ecma_value_t flags_value) /**< flags */ +{ + ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value); + uint16_t flags = 0; + + if (JERRY_UNLIKELY (pattern_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + if (!ecma_is_value_undefined (flags_value)) + { + ecma_string_t *flags_str_p = ecma_op_to_string (flags_value); + + if (JERRY_UNLIKELY (flags_str_p == NULL)) + { + ecma_deref_ecma_string (pattern_str_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t parse_flags_value = ecma_regexp_parse_flags (flags_str_p, &flags); + ecma_deref_ecma_string (flags_str_p); + + if (ECMA_IS_VALUE_ERROR (parse_flags_value)) + { + ecma_deref_ecma_string (pattern_str_p); + return parse_flags_value; + } + + JERRY_ASSERT (ecma_is_value_empty (parse_flags_value)); + } + + re_compiled_code_t *bc_p = re_compile_bytecode (pattern_str_p, flags); + + if (JERRY_UNLIKELY (bc_p == NULL)) + { + ecma_deref_ecma_string (pattern_str_p); + return ECMA_VALUE_ERROR; + } + + ecma_op_regexp_initialize (regexp_obj_p, bc_p); + ecma_deref_ecma_string (pattern_str_p); + + return ecma_make_object_value (regexp_obj_p); +} /* ecma_op_create_regexp_from_pattern */ + +/** + * Method for creating a RegExp object from bytecode. + * + * Note: + * Allocation have to happen before invoking this function using ecma_op_regexp_alloc. + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_regexp_from_bytecode (ecma_object_t *regexp_obj_p, /**< RegExp object */ + re_compiled_code_t *bc_p) /**< bytecode */ +{ + ecma_bytecode_ref ((ecma_compiled_code_t *) bc_p); + + ecma_op_regexp_initialize (regexp_obj_p, bc_p); + + return ecma_make_object_value (regexp_obj_p); +} /* ecma_op_create_regexp_from_bytecode */ + +/** + * Method for creating a RegExp object from pattern with already parsed flags. + * + * Note: + * Allocation have to happen before invoking this function using ecma_op_regexp_alloc. + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_regexp_with_flags (ecma_object_t *regexp_obj_p, /**< RegExp object */ + ecma_value_t pattern_value, /**< pattern */ + uint16_t flags) /**< flags */ +{ + ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value); + + if (JERRY_UNLIKELY (pattern_str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + re_compiled_code_t *bc_p = re_compile_bytecode (pattern_str_p, flags); + ecma_deref_ecma_string (pattern_str_p); + + if (JERRY_UNLIKELY (bc_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_op_regexp_initialize (regexp_obj_p, bc_p); + + return ecma_make_object_value (regexp_obj_p); +} /* ecma_op_create_regexp_with_flags */ + +/** + * Canonicalize a character + * + * @return ecma_char_t canonicalized character + */ +lit_code_point_t +ecma_regexp_canonicalize_char (lit_code_point_t ch, /**< character */ + bool unicode) /**< unicode */ +{ + if (unicode) + { + /* In unicode mode the mappings contained in the CaseFolding.txt file should be used to canonicalize the character. + * These mappings generally correspond to the lowercase variant of the character, however there are some + * differences. In some cases the uppercase variant is used, in others the lowercase of the uppercase character is + * used, and there are also cases where the character has no case folding mapping even though it has upper/lower + * variants. Since lowercasing is the most common this is used as the default behaviour, and characters with + * differing behaviours are encoded in lookup tables. */ + + if (lit_char_fold_to_upper (ch)) + { + ch = lit_char_to_upper_case (ch, NULL); + JERRY_ASSERT (ch != LIT_MULTIPLE_CU); + } + + if (lit_char_fold_to_lower (ch)) + { + ch = lit_char_to_lower_case (ch, NULL); + JERRY_ASSERT (ch != LIT_MULTIPLE_CU); + } + + return ch; + } + + JERRY_UNUSED (unicode); + lit_code_point_t cu = lit_char_to_upper_case (ch, NULL); + + if (ch <= LIT_UTF8_1_BYTE_CODE_POINT_MAX || (cu > LIT_UTF8_1_BYTE_CODE_POINT_MAX && cu != LIT_MULTIPLE_CU)) + { + return cu; + } + + return ch; +} /* ecma_regexp_canonicalize_char */ + +/** + * RegExp Canonicalize abstract operation + * + * See also: ECMA-262 v5, 15.10.2.8 + * + * @return ecma_char_t canonicalized character + */ +static inline lit_code_point_t +ecma_regexp_canonicalize (lit_code_point_t ch, /**< character */ + uint16_t flags) /**< flags */ +{ + if (flags & RE_FLAG_IGNORE_CASE) + { + return ecma_regexp_canonicalize_char (ch, flags & RE_FLAG_UNICODE); + } + + return ch; +} /* ecma_regexp_canonicalize */ + +/** + * Check if a code point is matched by a class escape. + * + * @return true, if code point matches escape + * false, otherwise + */ +static bool +ecma_regexp_check_class_escape (lit_code_point_t cp, /**< char */ + ecma_class_escape_t escape) /**< escape */ +{ + switch (escape) + { + case RE_ESCAPE_DIGIT: + { + return (cp >= LIT_CHAR_0 && cp <= LIT_CHAR_9); + } + case RE_ESCAPE_NOT_DIGIT: + { + return (cp < LIT_CHAR_0 || cp > LIT_CHAR_9); + } + case RE_ESCAPE_WORD_CHAR: + { + return lit_char_is_word_char (cp); + } + case RE_ESCAPE_NOT_WORD_CHAR: + { + return !lit_char_is_word_char (cp); + } + case RE_ESCAPE_WHITESPACE: + { + return lit_char_is_white_space ((ecma_char_t) cp); + } + case RE_ESCAPE_NOT_WHITESPACE: + { + return !lit_char_is_white_space ((ecma_char_t) cp); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* ecma_regexp_check_class_escape */ + +/** + * Helper function to get current code point or code unit depending on execution mode, + * and advance the string pointer. + * + * @return lit_code_point_t current code point + */ +static lit_code_point_t +ecma_regexp_advance (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + const lit_utf8_byte_t **str_p) /**< reference to string pointer */ +{ + JERRY_ASSERT (str_p != NULL); + lit_code_point_t cp = lit_cesu8_read_next (str_p); + + if (JERRY_UNLIKELY (re_ctx_p->flags & RE_FLAG_UNICODE) && lit_is_code_point_utf16_high_surrogate ((ecma_char_t) cp) + && *str_p < re_ctx_p->input_end_p) + { + const ecma_char_t next_ch = lit_cesu8_peek_next (*str_p); + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + cp = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) cp, next_ch); + *str_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + return ecma_regexp_canonicalize (cp, re_ctx_p->flags); +} /* ecma_regexp_advance */ + +/** + * Helper function to get current full unicode code point and advance the string pointer. + * + * @return lit_code_point_t current code point + */ +lit_code_point_t +ecma_regexp_unicode_advance (const lit_utf8_byte_t **str_p, /**< reference to string pointer */ + const lit_utf8_byte_t *end_p) /**< string end pointer */ +{ + JERRY_ASSERT (str_p != NULL); + const lit_utf8_byte_t *current_p = *str_p; + + lit_code_point_t ch = lit_cesu8_read_next (¤t_p); + if (lit_is_code_point_utf16_high_surrogate ((ecma_char_t) ch) && current_p < end_p) + { + const ecma_char_t next_ch = lit_cesu8_peek_next (current_p); + if (lit_is_code_point_utf16_low_surrogate (next_ch)) + { + ch = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) ch, next_ch); + current_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + *str_p = current_p; + return ch; +} /* ecma_regexp_unicode_advance */ + +/** + * Helper function to revert the string pointer to the previous code point. + * + * @return pointer to previous code point + */ +static JERRY_ATTR_NOINLINE const lit_utf8_byte_t * +ecma_regexp_step_back (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + const lit_utf8_byte_t *str_p) /**< reference to string pointer */ +{ + JERRY_ASSERT (str_p != NULL); + + lit_code_point_t ch = lit_cesu8_read_prev (&str_p); + if (JERRY_UNLIKELY (re_ctx_p->flags & RE_FLAG_UNICODE) && lit_is_code_point_utf16_low_surrogate (ch) + && lit_is_code_point_utf16_high_surrogate (lit_cesu8_peek_prev (str_p))) + { + str_p -= LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + + return str_p; +} /* ecma_regexp_step_back */ + +/** + * Check if the current poisition is on a word boundary. + * + * @return true, if on a word boundary + * false - otherwise + */ +static bool +ecma_regexp_is_word_boundary (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + const lit_utf8_byte_t *str_p) /**< string pointer */ +{ + lit_code_point_t left_cp; + lit_code_point_t right_cp; + + if (JERRY_UNLIKELY (str_p <= re_ctx_p->input_start_p)) + { + left_cp = LIT_INVALID_CP; + } + else if (JERRY_UNLIKELY ((re_ctx_p->flags & (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE)) + == (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE))) + { + const lit_utf8_byte_t *prev_p = ecma_regexp_step_back (re_ctx_p, str_p); + left_cp = ecma_regexp_advance (re_ctx_p, &prev_p); + JERRY_ASSERT (prev_p == str_p); + } + else + { + left_cp = str_p[-1]; + } + + if (JERRY_UNLIKELY (str_p >= re_ctx_p->input_end_p)) + { + right_cp = LIT_INVALID_CP; + } + else if (JERRY_UNLIKELY ((re_ctx_p->flags & (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE)) + == (RE_FLAG_UNICODE | RE_FLAG_IGNORE_CASE))) + { + right_cp = ecma_regexp_advance (re_ctx_p, &str_p); + } + else + { + right_cp = str_p[0]; + } + + return lit_char_is_word_char (left_cp) != lit_char_is_word_char (right_cp); +} /* ecma_regexp_is_word_boundary */ + +/** + * Recursive function for executing RegExp bytecode. + * + * See also: + * ECMA-262 v5, 15.10.2.1 + * + * @return pointer to the end of the currently matched substring + * NULL, if pattern did not match + */ +static const lit_utf8_byte_t * +ecma_regexp_run (ecma_regexp_ctx_t *re_ctx_p, /**< RegExp matcher context */ + const uint8_t *bc_p, /**< pointer to the current RegExp bytecode */ + const lit_utf8_byte_t *str_curr_p) /**< input string pointer */ +{ +#if (JERRY_STACK_LIMIT != 0) + if (JERRY_UNLIKELY (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT)) + { + return ECMA_RE_OUT_OF_STACK; + } +#endif /* JERRY_STACK_LIMIT != 0 */ + + const lit_utf8_byte_t *str_start_p = str_curr_p; + const uint8_t *next_alternative_p = NULL; + + while (true) + { + const re_opcode_t op = re_get_opcode (&bc_p); + + switch (op) + { + case RE_OP_EOF: + { + re_ctx_p->captures_p[RE_GLOBAL_CAPTURE].end_p = str_curr_p; + /* FALLTHRU */ + } + case RE_OP_ASSERT_END: + case RE_OP_ITERATOR_END: + { + return str_curr_p; + } + case RE_OP_ALTERNATIVE_START: + { + const uint32_t offset = re_get_value (&bc_p); + next_alternative_p = bc_p + offset; + continue; + } + case RE_OP_ALTERNATIVE_NEXT: + { + while (true) + { + const uint32_t offset = re_get_value (&bc_p); + bc_p += offset; + + if (*bc_p != RE_OP_ALTERNATIVE_NEXT) + { + break; + } + + bc_p++; + } + + continue; + } + case RE_OP_NO_ALTERNATIVE: + { + return NULL; + } + case RE_OP_CAPTURING_GROUP_START: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx; + group_p->subcapture_count = re_get_value (&bc_p); + + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + const lit_utf8_byte_t *const saved_end_p = group_p->end_p; + const uint32_t saved_iterator = group_p->iterator; + + const uint32_t qmin = re_get_value (&bc_p); + group_p->end_p = NULL; + + /* If zero iterations are allowed, then execute the end opcode which will handle further iterations, + * otherwise run the 1st iteration immediately by executing group bytecode. */ + if (qmin == 0) + { + group_p->iterator = 0; + group_p->begin_p = NULL; + const uint32_t end_offset = re_get_value (&bc_p); + group_p->bc_p = bc_p; + + bc_p += end_offset; + } + else + { + group_p->iterator = 1; + group_p->begin_p = str_curr_p; + group_p->bc_p = bc_p; + } + + const lit_utf8_byte_t *matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + group_p->iterator = saved_iterator; + + if (matched_p == NULL) + { + group_p->begin_p = saved_begin_p; + group_p->end_p = saved_end_p; + goto fail; + } + + return matched_p; + } + case RE_OP_NON_CAPTURING_GROUP_START: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx; + + group_p->subcapture_start = re_get_value (&bc_p); + group_p->subcapture_count = re_get_value (&bc_p); + + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + const uint32_t saved_iterator = group_p->iterator; + const uint32_t qmin = re_get_value (&bc_p); + + /* If zero iterations are allowed, then execute the end opcode which will handle further iterations, + * otherwise run the 1st iteration immediately by executing group bytecode. */ + if (qmin == 0) + { + group_p->iterator = 0; + group_p->begin_p = NULL; + const uint32_t end_offset = re_get_value (&bc_p); + group_p->bc_p = bc_p; + + bc_p += end_offset; + } + else + { + group_p->iterator = 1; + group_p->begin_p = str_curr_p; + group_p->bc_p = bc_p; + } + + const lit_utf8_byte_t *matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + group_p->iterator = saved_iterator; + + if (matched_p == NULL) + { + group_p->begin_p = saved_begin_p; + goto fail; + } + + return matched_p; + } + case RE_OP_GREEDY_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* No need to save begin_p since we don't have to backtrack beyond the minimum iteration count, but we have + * to clear nested capturing groups. */ + group_p->begin_p = str_curr_p; + for (uint32_t i = 1; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations, try to match tail bytecode. */ + group_p->end_p = str_curr_p; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + saved_captures_p[i] = group_p[i].begin_p; + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Failed to iterate again, backtrack to current match, and try to run tail bytecode. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + group_p->end_p = str_curr_p; + } + + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + goto fail; + } + case RE_OP_GREEDY_NON_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* No need to save begin_p but we have to clear nested capturing groups. */ + group_p->begin_p = str_curr_p; + + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start; + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + capture_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations, try to match tail bytecode. */ + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + saved_captures_p[i] = capture_p->begin_p; + capture_p->begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Failed to iterate again, backtrack to current match, and try to run tail bytecode. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + capture_p->begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + group_p->begin_p = saved_begin_p; + } + + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + goto fail; + } + case RE_OP_LAZY_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* No need to save begin_p but we have to clear nested capturing groups. */ + group_p->begin_p = str_curr_p; + for (uint32_t i = 1; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + group_p->end_p = str_curr_p; + + /* Try to match tail bytecode. */ + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations and tail bytecode did not match. */ + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + saved_captures_p[i] = group_p[i].begin_p; + group_p[i].begin_p = NULL; + } + + group_p->iterator++; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Backtrack to current match. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + group_p[i].begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + } + + goto fail; + } + case RE_OP_LAZY_NON_CAPTURING_GROUP_END: + { + const uint32_t group_idx = re_get_value (&bc_p); + ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx; + const uint32_t qmin = re_get_value (&bc_p); + + if (group_p->iterator < qmin) + { + /* Clear nested captures. */ + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start; + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + capture_p[i].begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + group_p->iterator--; + goto fail; + } + + /* Empty matches are not allowed after reaching the minimum number of iterations. */ + if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin)) + { + goto fail; + } + + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + + /* Try to match tail bytecode. */ + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (group_p->iterator >= qmax)) + { + /* Reached maximum number of iterations and tail bytecode did not match. */ + goto fail; + } + + { + /* Save and clear all nested capturing groups, and try to iterate. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count); + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + saved_captures_p[i] = capture_p->begin_p; + capture_p->begin_p = NULL; + } + + group_p->iterator++; + const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p; + group_p->begin_p = str_curr_p; + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p); + + if (matched_p != NULL) + { + return matched_p; + } + + /* Backtrack to current match. */ + for (uint32_t i = 0; i < group_p->subcapture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i; + capture_p->begin_p = saved_captures_p[i]; + } + + group_p->iterator--; + group_p->begin_p = saved_begin_p; + } + + goto fail; + } + case RE_OP_GREEDY_ITERATOR: + { + const uint32_t qmin = re_get_value (&bc_p); + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + const uint32_t end_offset = re_get_value (&bc_p); + + uint32_t iterator = 0; + while (iterator < qmin) + { + str_curr_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (str_curr_p == NULL) + { + goto fail; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p)) + { + return str_curr_p; + } + + iterator++; + } + + while (iterator < qmax) + { + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p == NULL) + { + break; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p)) + { + return str_curr_p; + } + + str_curr_p = matched_p; + iterator++; + } + + const uint8_t *const tail_bc_p = bc_p + end_offset; + while (true) + { + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, tail_bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (iterator <= qmin)) + { + goto fail; + } + + iterator--; + JERRY_ASSERT (str_curr_p > re_ctx_p->input_start_p); + str_curr_p = ecma_regexp_step_back (re_ctx_p, str_curr_p); + } + + JERRY_UNREACHABLE (); + } + case RE_OP_LAZY_ITERATOR: + { + const uint32_t qmin = re_get_value (&bc_p); + const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET; + const uint32_t end_offset = re_get_value (&bc_p); + + uint32_t iterator = 0; + while (iterator < qmin) + { + str_curr_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (str_curr_p == NULL) + { + goto fail; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p)) + { + return str_curr_p; + } + + iterator++; + } + + const uint8_t *const tail_bc_p = bc_p + end_offset; + while (true) + { + const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, tail_bc_p, str_curr_p); + + if (tail_match_p != NULL) + { + return tail_match_p; + } + + if (JERRY_UNLIKELY (iterator >= qmax)) + { + goto fail; + } + + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (matched_p == NULL) + { + goto fail; + } + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + return matched_p; + } + + iterator++; + str_curr_p = matched_p; + } + + JERRY_UNREACHABLE (); + } + case RE_OP_BACKREFERENCE: + { + const uint32_t backref_idx = re_get_value (&bc_p); + JERRY_ASSERT (backref_idx >= 1 && backref_idx < re_ctx_p->captures_count); + const ecma_regexp_capture_t *capture_p = re_ctx_p->captures_p + backref_idx; + + if (!ECMA_RE_IS_CAPTURE_DEFINED (capture_p) || capture_p->end_p <= capture_p->begin_p) + { + /* Undefined or zero length captures always match. */ + continue; + } + + const lit_utf8_size_t capture_size = (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p); + + if (str_curr_p + capture_size > re_ctx_p->input_end_p || memcmp (str_curr_p, capture_p->begin_p, capture_size)) + { + goto fail; + } + + str_curr_p += capture_size; + continue; + } + case RE_OP_ASSERT_LINE_START: + { + if (str_curr_p <= re_ctx_p->input_start_p) + { + continue; + } + + if (!(re_ctx_p->flags & RE_FLAG_MULTILINE) || !lit_char_is_line_terminator (lit_cesu8_peek_prev (str_curr_p))) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_LINE_END: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + continue; + } + + if (!(re_ctx_p->flags & RE_FLAG_MULTILINE) || !lit_char_is_line_terminator (lit_cesu8_peek_next (str_curr_p))) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_WORD_BOUNDARY: + { + if (!ecma_regexp_is_word_boundary (re_ctx_p, str_curr_p)) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_NOT_WORD_BOUNDARY: + { + if (ecma_regexp_is_word_boundary (re_ctx_p, str_curr_p)) + { + goto fail; + } + + continue; + } + case RE_OP_ASSERT_LOOKAHEAD_POS: + { + const uint8_t qmin = re_get_byte (&bc_p); + const uint32_t capture_start = re_get_value (&bc_p); + const uint32_t capture_count = re_get_value (&bc_p); + const uint32_t end_offset = re_get_value (&bc_p); + + /* If qmin is zero, the assertion implicitly matches. */ + if (qmin == 0) + { + bc_p += end_offset; + continue; + } + + /* Capture end pointers might get clobbered and need to be restored after a tail match fail. */ + JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, capture_count); + for (uint32_t i = 0; i < capture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + capture_start + i; + saved_captures_p[i] = capture_p->end_p; + } + + /* The first iteration will decide whether the assertion matches depending on whether + * the iteration matched or not. */ + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + return matched_p; + } + + if (matched_p == NULL) + { + goto fail; + } + + const lit_utf8_byte_t *tail_match_p = ecma_regexp_run (re_ctx_p, bc_p + end_offset, str_curr_p); + + if (tail_match_p == NULL) + { + for (uint32_t i = 0; i < capture_count; ++i) + { + ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + capture_start + i; + capture_p->begin_p = NULL; + capture_p->end_p = saved_captures_p[i]; + } + + goto fail; + } + + return tail_match_p; + } + case RE_OP_ASSERT_LOOKAHEAD_NEG: + { + const uint8_t qmin = re_get_byte (&bc_p); + uint32_t capture_idx = re_get_value (&bc_p); + const uint32_t capture_count = re_get_value (&bc_p); + const uint32_t end_offset = re_get_value (&bc_p); + + /* If qmin is zero, the assertion implicitly matches. */ + if (qmin > 0) + { + /* The first iteration will decide whether the assertion matches depending on whether + * the iteration matched or not. */ + const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + return matched_p; + } + + if (matched_p != NULL) + { + /* Nested capturing groups inside a negative lookahead can never capture, so we clear their results. */ + const uint32_t capture_end = capture_idx + capture_count; + while (capture_idx < capture_end) + { + re_ctx_p->captures_p[capture_idx++].begin_p = NULL; + } + + goto fail; + } + } + + bc_p += end_offset; + continue; + } + case RE_OP_CLASS_ESCAPE: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const lit_code_point_t cp = ecma_regexp_advance (re_ctx_p, &str_curr_p); + + const ecma_class_escape_t escape = (ecma_class_escape_t) re_get_byte (&bc_p); + if (!ecma_regexp_check_class_escape (cp, escape)) + { + goto fail; + } + + continue; + } + case RE_OP_CHAR_CLASS: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + uint8_t flags = re_get_byte (&bc_p); + uint32_t char_count = (flags & RE_CLASS_HAS_CHARS) ? re_get_value (&bc_p) : 0; + uint32_t range_count = (flags & RE_CLASS_HAS_RANGES) ? re_get_value (&bc_p) : 0; + + const lit_code_point_t cp = ecma_regexp_advance (re_ctx_p, &str_curr_p); + + uint8_t escape_count = flags & RE_CLASS_ESCAPE_COUNT_MASK; + while (escape_count > 0) + { + escape_count--; + const ecma_class_escape_t escape = (ecma_class_escape_t) re_get_byte (&bc_p); + if (ecma_regexp_check_class_escape (cp, escape)) + { + goto class_found; + } + } + + while (char_count > 0) + { + char_count--; + const lit_code_point_t curr = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + if (cp == curr) + { + goto class_found; + } + } + + while (range_count > 0) + { + range_count--; + const lit_code_point_t begin = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + + if (cp < begin) + { + bc_p += re_ctx_p->char_size; + continue; + } + + const lit_code_point_t end = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + if (cp <= end) + { + goto class_found; + } + } + + /* Not found */ + if (flags & RE_CLASS_INVERT) + { + continue; + } + + goto fail; + +class_found: + if (flags & RE_CLASS_INVERT) + { + goto fail; + } + + const uint32_t chars_size = char_count * re_ctx_p->char_size; + const uint32_t ranges_size = range_count * re_ctx_p->char_size * 2; + bc_p = bc_p + escape_count + chars_size + ranges_size; + continue; + } + case RE_OP_UNICODE_PERIOD: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const lit_code_point_t cp = ecma_regexp_unicode_advance (&str_curr_p, re_ctx_p->input_end_p); + + if (!(re_ctx_p->flags & RE_FLAG_DOTALL) + && JERRY_UNLIKELY (cp <= LIT_UTF16_CODE_UNIT_MAX && lit_char_is_line_terminator ((ecma_char_t) cp))) + { + goto fail; + } + + continue; + } + case RE_OP_PERIOD: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const ecma_char_t ch = lit_cesu8_read_next (&str_curr_p); + + if (!(re_ctx_p->flags & RE_FLAG_DOTALL) && lit_char_is_line_terminator (ch)) + { + goto fail; + } + + continue; + } + case RE_OP_CHAR: + { + if (str_curr_p >= re_ctx_p->input_end_p) + { + goto fail; + } + + const lit_code_point_t ch1 = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE); + const lit_code_point_t ch2 = ecma_regexp_advance (re_ctx_p, &str_curr_p); + + if (ch1 != ch2) + { + goto fail; + } + + continue; + } + default: + { + JERRY_ASSERT (op == RE_OP_BYTE); + + if (str_curr_p >= re_ctx_p->input_end_p || *bc_p++ != *str_curr_p++) + { + goto fail; + } + + continue; + } + } + + JERRY_UNREACHABLE (); +fail: + bc_p = next_alternative_p; + + if (bc_p == NULL || *bc_p++ != RE_OP_ALTERNATIVE_NEXT) + { + /* None of the alternatives matched. */ + return NULL; + } + + /* Get the end of the new alternative and continue execution. */ + str_curr_p = str_start_p; + const uint32_t offset = re_get_value (&bc_p); + next_alternative_p = bc_p + offset; + } +} /* ecma_regexp_run */ + +/** + * Match a RegExp at a specific position in the input string. + * + * @return pointer to the end of the matched sub-string + * NULL, if pattern did not match + */ +static const lit_utf8_byte_t * +ecma_regexp_match (ecma_regexp_ctx_t *re_ctx_p, /**< RegExp matcher context */ + const uint8_t *bc_p, /**< pointer to the current RegExp bytecode */ + const lit_utf8_byte_t *str_curr_p) /**< input string pointer */ +{ + re_ctx_p->captures_p[RE_GLOBAL_CAPTURE].begin_p = str_curr_p; + + for (uint32_t i = 1; i < re_ctx_p->captures_count; ++i) + { + re_ctx_p->captures_p[i].begin_p = NULL; + } + + return ecma_regexp_run (re_ctx_p, bc_p, str_curr_p); +} /* ecma_regexp_match */ + +/* + * Helper function to get the result of a capture + * + * @return string value, if capture is defined + * undefined, otherwise + */ +ecma_value_t +ecma_regexp_get_capture_value (const ecma_regexp_capture_t *const capture_p) /**< capture */ +{ + if (ECMA_RE_IS_CAPTURE_DEFINED (capture_p)) + { + JERRY_ASSERT (capture_p->end_p >= capture_p->begin_p); + const lit_utf8_size_t capture_size = (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p); + ecma_string_t *const capture_str_p = ecma_new_ecma_string_from_utf8 (capture_p->begin_p, capture_size); + return ecma_make_string_value (capture_str_p); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_regexp_get_capture_value */ + +/** + * Helper function to create a result array from the captures in a regexp context + * + * @return ecma value containing the created array object + */ +static ecma_value_t +ecma_regexp_create_result_object (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */ + ecma_string_t *input_string_p, /**< input ecma string */ + uint32_t index) /**< match index */ +{ + ecma_object_t *result_p = ecma_op_new_array_object (0); + + for (uint32_t i = 0; i < re_ctx_p->captures_count; i++) + { + ecma_value_t capture_value = ecma_regexp_get_capture_value (re_ctx_p->captures_p + i); + ecma_builtin_helper_def_prop_by_index (result_p, i, capture_value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_free_value (capture_value); + } + + ecma_builtin_helper_def_prop (result_p, + ecma_get_magic_string (LIT_MAGIC_STRING_INDEX), + ecma_make_uint32_value (index), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + ecma_builtin_helper_def_prop (result_p, + ecma_get_magic_string (LIT_MAGIC_STRING_INPUT), + ecma_make_string_value (input_string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + return ecma_make_object_value (result_p); +} /* ecma_regexp_create_result_object */ + +/** + * Helper function to initialize a regexp match context + */ +static void +ecma_regexp_initialize_context (ecma_regexp_ctx_t *ctx_p, /**< regexp context */ + const re_compiled_code_t *bc_p, /**< regexp bytecode */ + const lit_utf8_byte_t *input_start_p, /**< pointer to input string */ + const lit_utf8_byte_t *input_end_p) /**< pointer to end of input string */ +{ + JERRY_ASSERT (ctx_p != NULL); + JERRY_ASSERT (bc_p != NULL); + JERRY_ASSERT (input_start_p != NULL); + JERRY_ASSERT (input_end_p >= input_start_p); + + ctx_p->flags = bc_p->header.status_flags; + ctx_p->char_size = (ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t); + + ctx_p->input_start_p = input_start_p; + ctx_p->input_end_p = input_end_p; + + ctx_p->captures_count = bc_p->captures_count; + ctx_p->non_captures_count = bc_p->non_captures_count; + + ctx_p->captures_p = (ecma_regexp_capture_t *) jmem_heap_alloc_block (ctx_p->captures_count * sizeof (ecma_regexp_capture_t)); + + if (ctx_p->non_captures_count > 0) + { + ctx_p->non_captures_p = (ecma_regexp_non_capture_t *) jmem_heap_alloc_block (ctx_p->non_captures_count * sizeof (ecma_regexp_non_capture_t)); + } +} /* ecma_regexp_initialize_context */ + +/** + * Helper function to clean up a regexp context + */ +static void +ecma_regexp_cleanup_context (ecma_regexp_ctx_t *ctx_p) /**< regexp context */ +{ + JERRY_ASSERT (ctx_p != NULL); + jmem_heap_free_block (ctx_p->captures_p, ctx_p->captures_count * sizeof (ecma_regexp_capture_t)); + + if (ctx_p->non_captures_count > 0) + { + jmem_heap_free_block (ctx_p->non_captures_p, ctx_p->non_captures_count * sizeof (ecma_regexp_non_capture_t)); + } +} /* ecma_regexp_cleanup_context */ + +/** + * RegExp helper function to start the recursive matching algorithm + * and create the result Array object + * + * See also: + * ECMA-262 v5, 15.10.6.2 + * ECMA-262 v11, 21.2.5.2.2 + * + * @return array object - if matched + * null - otherwise + * + * May raise error. + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, /**< RegExp object */ + ecma_string_t *input_string_p) /**< input string */ +{ + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + lit_utf8_byte_t *matched_p; + uint8_t *bc_start_p; + + /* 1. */ + JERRY_ASSERT (ecma_object_is_regexp_object (ecma_make_object_value (regexp_object_p))); + + /* 9. */ + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) regexp_object_p; + re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ext_object_p->u.cls.u3.value); + + /* 3. */ + lit_utf8_size_t input_size; + lit_utf8_size_t input_length; + uint8_t input_flags = ECMA_STRING_FLAG_IS_ASCII; + const lit_utf8_byte_t *input_buffer_p = + ecma_string_get_chars (input_string_p, &input_size, &input_length, NULL, &input_flags); + + const lit_utf8_byte_t *input_curr_p = input_buffer_p; + const lit_utf8_byte_t *input_end_p = input_buffer_p + input_size; + + ecma_regexp_ctx_t re_ctx; + ecma_regexp_initialize_context (&re_ctx, bc_p, input_buffer_p, input_end_p); + + /* 4. */ + ecma_length_t index = 0; + ecma_value_t lastindex_value = ecma_op_object_get_by_magic_id (regexp_object_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + ret_value = ecma_op_to_length (lastindex_value, &index); + ecma_free_value (lastindex_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + goto cleanup_context; + } + + if (re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY)) + { + /* 12.a */ + if (index > input_length) + { + goto fail_put_lastindex; + } + + if (index > 0) + { + if (input_flags & ECMA_STRING_FLAG_IS_ASCII) + { + input_curr_p += index; + } + else + { + for (uint32_t i = 0; i < index; i++) + { + lit_utf8_incr (&input_curr_p); + } + } + } + } + /* 8. */ + else + { + index = 0; + } + + /* 9. */ + bc_start_p = (uint8_t *) (bc_p + 1); + + /* 11. */ + matched_p = NULL; + + /* 12. */ + JERRY_ASSERT (index <= input_length); + while (true) + { + matched_p = (lit_utf8_byte_t *) ecma_regexp_match (&re_ctx, bc_start_p, input_curr_p); + + if (matched_p != NULL) + { + goto match_found; + } + + /* 12.c.i */ + if (re_ctx.flags & RE_FLAG_STICKY) + { + goto fail_put_lastindex; + } + + /* 12.a */ + if (input_curr_p >= input_end_p) + { + if (re_ctx.flags & RE_FLAG_GLOBAL) + { + goto fail_put_lastindex; + } + + goto match_failed; + } + + JERRY_ASSERT (input_curr_p < input_end_p); + + /* 12.c.ii */ + index++; + + if (re_ctx.flags & RE_FLAG_UNICODE) + { + const lit_code_point_t cp = ecma_regexp_unicode_advance (&input_curr_p, input_end_p); + + if (cp > LIT_UTF16_CODE_UNIT_MAX) + { + index++; + } + + continue; + } + + lit_utf8_incr (&input_curr_p); + } + + JERRY_UNREACHABLE (); + +fail_put_lastindex: + /* We should only get here if the regexp is global or sticky */ + JERRY_ASSERT ((re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY)) != 0); + + ret_value = ecma_op_object_put (regexp_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_integer_value (0), + true); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + goto cleanup_context; + } + + JERRY_ASSERT (ecma_is_value_boolean (ret_value)); + +match_failed: + /* 12.a.ii */ + ret_value = ECMA_VALUE_NULL; + goto cleanup_context; + +match_found: + JERRY_ASSERT (matched_p != NULL); + + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + ret_value = ecma_raise_range_error (ECMA_ERR_STACK_LIMIT_EXCEEDED); + goto cleanup_context; + } + + JERRY_ASSERT (index <= input_length); + + /* 15. */ + if (re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY)) + { + /* 13-14. */ + lit_utf8_size_t match_length; + const lit_utf8_byte_t *match_begin_p = re_ctx.captures_p[0].begin_p; + const lit_utf8_byte_t *match_end_p = re_ctx.captures_p[0].end_p; + + if (input_flags & ECMA_STRING_FLAG_IS_ASCII) + { + match_length = (lit_utf8_size_t) (match_end_p - match_begin_p); + } + else + { + match_length = lit_utf8_string_length (match_begin_p, (lit_utf8_size_t) (match_end_p - match_begin_p)); + } + + ret_value = ecma_op_object_put (regexp_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value ((uint32_t) index + match_length), + true); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + goto cleanup_context; + } + + JERRY_ASSERT (ecma_is_value_boolean (ret_value)); + } + + /* 16-27. */ + ret_value = ecma_regexp_create_result_object (&re_ctx, input_string_p, (uint32_t) index); + +cleanup_context: + ecma_regexp_cleanup_context (&re_ctx); + + if (input_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) input_buffer_p, input_size); + } + + return ret_value; +} /* ecma_regexp_exec_helper */ + +/** + * Helper function for converting a RegExp pattern parameter to string. + * + * See also: + * RegExp.compile + * RegExp dispatch call + * + * @return empty value if success, error value otherwise + * Returned value must be freed with ecma_free_value. + */ +ecma_string_t * +ecma_regexp_read_pattern_str_helper (ecma_value_t pattern_arg) /**< the RegExp pattern */ +{ + if (!ecma_is_value_undefined (pattern_arg)) + { + ecma_string_t *pattern_string_p = ecma_op_to_string (pattern_arg); + if (JERRY_UNLIKELY (pattern_string_p == NULL) || !ecma_string_is_empty (pattern_string_p)) + { + return pattern_string_p; + } + } + + return ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); +} /* ecma_regexp_read_pattern_str_helper */ + +/** + * Helper function for RegExp based string searches + * + * See also: + * ECMA-262 v6, 21.2.5.9 + * + * @return index of the match + */ +ecma_value_t +ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */ + ecma_value_t string_arg) /**< string argument */ +{ + /* 2. */ + if (!ecma_is_value_object (regexp_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_value_t result = ECMA_VALUE_ERROR; + ecma_value_t current_last_index; + ecma_value_t match; + bool same_value; + + /* 3. */ + ecma_string_t *const string_p = ecma_op_to_string (string_arg); + if (string_p == NULL) + { + return result; + } + + ecma_object_t *const regexp_object_p = ecma_get_object_from_value (regexp_arg); + + /* 4. */ + ecma_string_t *const last_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); + const ecma_value_t prev_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p); + if (ECMA_IS_VALUE_ERROR (prev_last_index)) + { + goto cleanup_string; + } + + /* 5. */ + if (prev_last_index != ecma_make_uint32_value (0)) + { + const ecma_value_t status = + ecma_op_object_put (regexp_object_p, last_index_str_p, ecma_make_uint32_value (0), true); + + if (ECMA_IS_VALUE_ERROR (status)) + { + goto cleanup_prev_last_index; + } + + JERRY_ASSERT (ecma_is_value_boolean (status)); + } + + /* 6. */ + match = ecma_op_regexp_exec (regexp_arg, string_p); + if (ECMA_IS_VALUE_ERROR (match)) + { + goto cleanup_prev_last_index; + } + + /* 7. */ + current_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p); + if (ECMA_IS_VALUE_ERROR (current_last_index)) + { + ecma_free_value (match); + goto cleanup_prev_last_index; + } + + same_value = ecma_op_same_value (prev_last_index, current_last_index); + + ecma_free_value (current_last_index); + + /* 8. */ + if (!same_value) + { + result = ecma_op_object_put (regexp_object_p, last_index_str_p, prev_last_index, true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (match); + goto cleanup_prev_last_index; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + } + + /* 9-10. */ + if (ecma_is_value_null (match)) + { + result = ecma_make_int32_value (-1); + } + else + { + ecma_object_t *const match_p = ecma_get_object_from_value (match); + result = ecma_op_object_get_by_magic_id (match_p, LIT_MAGIC_STRING_INDEX); + ecma_deref_object (match_p); + } + +cleanup_prev_last_index: + ecma_free_value (prev_last_index); + +cleanup_string: + ecma_deref_ecma_string (string_p); + return result; +} /* ecma_regexp_search_helper */ + +/** + * Helper function for RegExp based string split operation + * + * See also: + * ECMA-262 v6, 21.2.5.11 + * + * @return array of split and captured strings + */ +ecma_value_t +ecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */ + ecma_value_t string_arg, /**< string value */ + ecma_value_t limit_arg) /**< limit value */ +{ + /* 2. */ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_value_t result = ECMA_VALUE_ERROR; + ecma_length_t current_index; + ecma_length_t previous_index; + ecma_object_t *constructor_obj_p; + ecma_value_t flags; + ecma_string_t *flags_str_p; + lit_utf8_size_t flags_size; + uint8_t flags_str_flags; + lit_utf8_byte_t *flags_buffer_p; + lit_utf8_byte_t *flags_end_p; + ecma_value_t arguments[2]; + ecma_value_t splitter; + ecma_object_t *splitter_obj_p; + ecma_object_t *array_p; + ecma_value_t array; + ecma_string_t *end_str_p; + ecma_string_t *lastindex_str_p; + lit_utf8_size_t string_length; + uint32_t array_length; + uint32_t limit; + bool unicode; + bool sticky; + + /* 3-4. */ + ecma_string_t *const string_p = ecma_op_to_string (string_arg); + if (string_p == NULL) + { + return result; + } + + /* 5-6. */ + ecma_object_t *const regexp_obj_p = ecma_get_object_from_value (this_arg); + ecma_value_t constructor = ecma_op_species_constructor (regexp_obj_p, ECMA_BUILTIN_ID_REGEXP); + if (ECMA_IS_VALUE_ERROR (constructor)) + { + goto cleanup_string; + } + + constructor_obj_p = ecma_get_object_from_value (constructor); + + /* 7-8. */ + flags = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS); + if (ECMA_IS_VALUE_ERROR (flags)) + { + ecma_deref_object (constructor_obj_p); + goto cleanup_string; + } + + flags_str_p = ecma_op_to_string (flags); + ecma_free_value (flags); + + if (JERRY_UNLIKELY (flags_str_p == NULL)) + { + ecma_deref_object (constructor_obj_p); + goto cleanup_string; + } + + flags_str_flags = ECMA_STRING_FLAG_IS_ASCII; + flags_buffer_p = (lit_utf8_byte_t *) ecma_string_get_chars (flags_str_p, &flags_size, NULL, NULL, &flags_str_flags); + + unicode = false; + sticky = false; + + /* 9-11. */ + flags_end_p = flags_buffer_p + flags_size; + for (const lit_utf8_byte_t *current_p = flags_buffer_p; current_p < flags_end_p; ++current_p) + { + switch (*current_p) + { + case LIT_CHAR_LOWERCASE_U: + { + unicode = true; + break; + } + case LIT_CHAR_LOWERCASE_Y: + { + sticky = true; + break; + } + } + } + + if (flags_str_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) flags_buffer_p, flags_size); + } + + /* 12. */ + if (!sticky) + { + ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (flags_str_p); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_LOWERCASE_Y); + + ecma_deref_ecma_string (flags_str_p); + flags_str_p = ecma_stringbuilder_finalize (&builder); + } + + /* 13-14. */ + arguments[0] = this_arg; + arguments[1] = ecma_make_string_value (flags_str_p); + splitter = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, arguments, 2); + + ecma_deref_ecma_string (flags_str_p); + ecma_deref_object (constructor_obj_p); + + if (ECMA_IS_VALUE_ERROR (splitter)) + { + goto cleanup_string; + } + + splitter_obj_p = ecma_get_object_from_value (splitter); + + /* 17. */ + limit = UINT32_MAX - 1; + if (!ecma_is_value_undefined (limit_arg)) + { + /* ECMA-262 v11, 21.2.5.13 13 */ + ecma_number_t num; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (limit_arg, &num))) + { + goto cleanup_splitter; + } + limit = ecma_number_to_uint32 (num); + } + + /* 15. */ + array_p = ecma_op_new_array_object (0); + array = ecma_make_object_value (array_p); + + /* 21. */ + if (limit == 0) + { + result = array; + goto cleanup_splitter; + } + + string_length = ecma_string_get_length (string_p); + array_length = 0; + + /* 22. */ + if (string_length == 0) + { + const ecma_value_t match = ecma_op_regexp_exec (splitter, string_p); + + if (ECMA_IS_VALUE_ERROR (match)) + { + goto cleanup_array; + } + + if (ecma_is_value_null (match)) + { + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length, + ecma_make_string_value (string_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + } + + ecma_free_value (match); + result = array; + goto cleanup_splitter; + } + + /* 23. */ + current_index = 0; + previous_index = 0; + + lastindex_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); + + /* 24. */ + while (current_index < string_length) + { + /* 24.a-b. */ + ecma_value_t index_value = ecma_make_length_value (current_index); + result = ecma_op_object_put (splitter_obj_p, lastindex_str_p, index_value, true); + + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_array; + } + + JERRY_ASSERT (ecma_is_value_true (result)); + + /* 24.c-d. */ + result = ecma_op_regexp_exec (splitter, string_p); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_array; + } + + /* 24.e. */ + if (ecma_is_value_null (result)) + { + current_index = ecma_op_advance_string_index (string_p, current_index, unicode); + continue; + } + + ecma_object_t *const match_array_p = ecma_get_object_from_value (result); + + /* 24.f.i. */ + result = ecma_op_object_get (splitter_obj_p, lastindex_str_p); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + ecma_length_t end_index; + const ecma_value_t length_value = ecma_op_to_length (result, &end_index); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (length_value)) + { + result = ECMA_VALUE_ERROR; + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + /* ECMA-262 v11, 21.2.5.11 19.d.ii */ + if (end_index > string_length) + { + end_index = string_length; + } + + /* 24.f.iii. */ + if (previous_index == end_index) + { + ecma_deref_object (match_array_p); + current_index = ecma_op_advance_string_index (string_p, current_index, unicode); + continue; + } + + /* 24.f.iv.1-4. */ + JERRY_ASSERT (previous_index <= string_length && current_index <= string_length); + ecma_string_t *const split_str_p = + ecma_string_substr (string_p, (lit_utf8_size_t) previous_index, (lit_utf8_size_t) current_index); + + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + ecma_make_string_value (split_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + ecma_deref_ecma_string (split_str_p); + + /* 24.f.iv.5. */ + if (array_length == limit) + { + ecma_deref_object (match_array_p); + result = array; + goto cleanup_splitter; + } + + /* 24.f.iv.6. */ + previous_index = end_index; + + /* 24.f.iv.7-8. */ + ecma_length_t match_length; + result = ecma_op_object_get_length (match_array_p, &match_length); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + /* 24.f.iv.9. */ + match_length = (match_length > 0) ? match_length - 1 : match_length; + + ecma_length_t match_index = 1; + while (match_index <= match_length) + { + /* 24.f.iv.11.a-b. */ + result = ecma_op_object_get_by_index (match_array_p, match_index++); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_object (match_array_p); + goto cleanup_array; + } + + const ecma_value_t capture = result; + + /* 24.f.iv.11.c. */ + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + capture, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + + ecma_free_value (capture); + + if (array_length == limit) + { + ecma_deref_object (match_array_p); + result = array; + goto cleanup_splitter; + } + } + + /* 24.f.iv.12. */ + JERRY_ASSERT (end_index <= UINT32_MAX); + current_index = (uint32_t) end_index; + + ecma_deref_object (match_array_p); + } + + JERRY_ASSERT (previous_index <= string_length); + end_str_p = ecma_string_substr (string_p, (lit_utf8_size_t) previous_index, string_length); + result = ecma_builtin_helper_def_prop_by_index (array_p, + array_length++, + ecma_make_string_value (end_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (result)); + ecma_deref_ecma_string (end_str_p); + + result = array; + goto cleanup_splitter; + +cleanup_array: + ecma_deref_object (array_p); +cleanup_splitter: + ecma_deref_object (splitter_obj_p); +cleanup_string: + ecma_deref_ecma_string (string_p); + + return result; +} /* ecma_regexp_split_helper */ + +/** + * Fast path for RegExp based replace operation + * + * This method assumes the following: + * - The RegExp object is a built-in RegExp + * - The 'exec' method of the RegExp object is the built-in 'exec' method + * - The 'lastIndex' property is writable + * + * The standard would normally require us to first execute the regexp and collect the results, + * and after that iterate over the collected results and replace them. + * The assumptions above guarantee that during the matching phase there will be no exceptions thrown, + * which means we can do the match/replace in a single loop, without collecting the results. + * + * @return string value if successful + * thrown value otherwise + */ +static ecma_value_t +ecma_regexp_replace_helper_fast (ecma_replace_context_t *ctx_p, /**u.cls.u3.value); + ecma_bytecode_ref ((ecma_compiled_code_t *) bc_p); + + JERRY_ASSERT (bc_p != NULL); + + uint8_t string_flags = ECMA_STRING_FLAG_IS_ASCII; + lit_utf8_size_t string_length; + ctx_p->string_p = ecma_string_get_chars (string_p, &(ctx_p->string_size), &string_length, NULL, &string_flags); + + const lit_utf8_byte_t *const string_end_p = ctx_p->string_p + ctx_p->string_size; + const uint8_t *const bc_start_p = (const uint8_t *) (bc_p + 1); + const lit_utf8_byte_t *matched_p = NULL; + const lit_utf8_byte_t *current_p = ctx_p->string_p; + const lit_utf8_byte_t *last_append_p = current_p; + ecma_length_t index; + lit_utf8_size_t trailing_size; + + ecma_regexp_ctx_t re_ctx; + ecma_regexp_initialize_context (&re_ctx, bc_p, ctx_p->string_p, string_end_p); + + /* lastIndex must be accessed to remain consistent with the standard, even though we may not need the value. */ + ecma_value_t lastindex_value = + ecma_op_object_get_by_magic_id ((ecma_object_t *) re_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + ecma_value_t result = ecma_op_to_length (lastindex_value, &index); + ecma_free_value (lastindex_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_context; + } + + /* Only non-global sticky matches use the lastIndex value, otherwise the starting index is 0. */ + if (JERRY_UNLIKELY ((ctx_p->flags & RE_FLAG_GLOBAL) == 0 && (re_ctx.flags & RE_FLAG_STICKY) != 0)) + { + if (index > string_length) + { + result = ecma_op_object_put ((ecma_object_t *) re_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + true); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + JERRY_ASSERT (ecma_is_value_true (result)); + ecma_ref_ecma_string (string_p); + result = ecma_make_string_value (string_p); + } + + goto cleanup_context; + } + + if (string_flags & ECMA_STRING_FLAG_IS_ASCII) + { + current_p += index; + } + else + { + ecma_length_t counter = index; + while (counter--) + { + lit_utf8_incr (¤t_p); + } + } + } + else + { + index = 0; + } + + ctx_p->builder = ecma_stringbuilder_create (); + ctx_p->capture_count = re_ctx.captures_count; + ctx_p->u.captures_p = re_ctx.captures_p; + + while (true) + { + matched_p = ecma_regexp_match (&re_ctx, bc_start_p, current_p); + + if (matched_p != NULL) + { + if (ECMA_RE_STACK_LIMIT_REACHED (matched_p)) + { + result = ecma_raise_range_error (ECMA_ERR_STACK_LIMIT_EXCEEDED); + goto cleanup_builder; + } + + const lit_utf8_size_t remaining_size = (lit_utf8_size_t) (current_p - last_append_p); + ecma_stringbuilder_append_raw (&(ctx_p->builder), last_append_p, remaining_size); + + if (ctx_p->replace_str_p != NULL) + { + ctx_p->matched_p = current_p; + const ecma_regexp_capture_t *const global_capture_p = re_ctx.captures_p; + ctx_p->matched_size = (lit_utf8_size_t) (global_capture_p->end_p - global_capture_p->begin_p); + ctx_p->match_byte_pos = (lit_utf8_size_t) (current_p - re_ctx.input_start_p); + + ecma_builtin_replace_substitute (ctx_p); + } + else + { + ecma_collection_t *arguments_p = ecma_new_collection (); + + for (uint32_t i = 0; i < re_ctx.captures_count; i++) + { + ecma_value_t capture = ecma_regexp_get_capture_value (re_ctx.captures_p + i); + ecma_collection_push_back (arguments_p, capture); + } + + ecma_collection_push_back (arguments_p, ecma_make_length_value (index)); + ecma_ref_ecma_string (string_p); + ecma_collection_push_back (arguments_p, ecma_make_string_value (string_p)); + ecma_object_t *function_p = ecma_get_object_from_value (replace_arg); + + result = + ecma_op_function_call (function_p, ECMA_VALUE_UNDEFINED, arguments_p->buffer_p, arguments_p->item_count); + + ecma_collection_free (arguments_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + /* 16.m.v */ + ecma_string_t *const replace_result_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (replace_result_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + ecma_stringbuilder_append (&(ctx_p->builder), replace_result_p); + ecma_deref_ecma_string (replace_result_p); + } + + const ecma_regexp_capture_t *global_capture_p = re_ctx.captures_p; + last_append_p = global_capture_p->end_p; + + const lit_utf8_size_t matched_size = (lit_utf8_size_t) (global_capture_p->end_p - global_capture_p->begin_p); + + const bool is_ascii = (string_flags & ECMA_STRING_FLAG_IS_ASCII) != 0; + index += is_ascii ? matched_size : lit_utf8_string_length (current_p, matched_size); + + if (!(ctx_p->flags & RE_FLAG_GLOBAL)) + { + if (JERRY_UNLIKELY ((re_ctx.flags & RE_FLAG_STICKY) != 0)) + { + ecma_value_t index_value = ecma_make_length_value (index); + result = ecma_op_object_put ((ecma_object_t *) re_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + index_value, + true); + + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + } + + break; + } + + if (matched_size > 0) + { + current_p = last_append_p; + continue; + } + } + else if (JERRY_UNLIKELY ((re_ctx.flags & RE_FLAG_STICKY) != 0)) + { + result = ecma_op_object_put ((ecma_object_t *) re_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + break; + } + + if (current_p >= string_end_p) + { + break; + } + + if ((ctx_p->flags & RE_FLAG_UNICODE) != 0) + { + index++; + const lit_code_point_t cp = ecma_regexp_unicode_advance (¤t_p, string_end_p); + + if (cp > LIT_UTF16_CODE_UNIT_MAX) + { + index++; + } + + continue; + } + + index++; + lit_utf8_incr (¤t_p); + } + + trailing_size = (lit_utf8_size_t) (string_end_p - last_append_p); + ecma_stringbuilder_append_raw (&(ctx_p->builder), last_append_p, trailing_size); + + result = ecma_make_string_value (ecma_stringbuilder_finalize (&(ctx_p->builder))); + goto cleanup_context; + +cleanup_builder: + ecma_stringbuilder_destroy (&(ctx_p->builder)); + +cleanup_context: + ecma_regexp_cleanup_context (&re_ctx); + ecma_bytecode_deref ((ecma_compiled_code_t *) bc_p); + + if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) ctx_p->string_p, ctx_p->string_size); + } + + return result; +} /* ecma_regexp_replace_helper_fast */ + +/** + * Helper function for RegExp based replacing + * + * See also: + * String.prototype.replace + * RegExp.prototype[@@replace] + * + * @return result string of the replacement, if successful + * error value, otherwise + */ +ecma_value_t +ecma_regexp_replace_helper (ecma_value_t this_arg, /**< this argument */ + ecma_value_t string_arg, /**< source string */ + ecma_value_t replace_arg) /**< replace string */ +{ + /* 2. */ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + lit_utf8_size_t index; + uint8_t string_flags; + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); + ecma_replace_context_t replace_ctx; + ecma_collection_t *results_p; + lit_utf8_size_t string_length; + lit_utf8_byte_t *source_position_p; + lit_utf8_byte_t *string_end_p; + + replace_ctx.flags = RE_FLAG_EMPTY; + + /* 3. */ + ecma_string_t *string_p = ecma_op_to_string (string_arg); + if (string_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ECMA_VALUE_ERROR; + + /* 6. */ + replace_ctx.replace_str_p = NULL; + if (!ecma_op_is_callable (replace_arg)) + { + replace_ctx.replace_str_p = ecma_op_to_string (replace_arg); + + if (replace_ctx.replace_str_p == NULL) + { + goto cleanup_string; + } + } + + /* 8 */ + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_GLOBAL); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + if (ecma_op_to_boolean (result)) + { + replace_ctx.flags |= RE_FLAG_GLOBAL; + } + + ecma_free_value (result); + + string_length = ecma_string_get_length (string_p); + + /* 10. */ + if (replace_ctx.flags & RE_FLAG_GLOBAL) + { + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_UNICODE); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + if (ecma_op_to_boolean (result)) + { + replace_ctx.flags |= RE_FLAG_UNICODE; + } + + ecma_free_value (result); + + result = ecma_op_object_put (this_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + true); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + } + + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_EXEC); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_replace; + } + + /* Check for fast path. */ + if (ecma_op_is_callable (result)) + { + ecma_extended_object_t *function_p = (ecma_extended_object_t *) ecma_get_object_from_value (result); + if (ecma_object_class_is (this_obj_p, ECMA_OBJECT_CLASS_REGEXP) && ecma_builtin_is_regexp_exec (function_p)) + { + ecma_deref_object ((ecma_object_t *) function_p); + + result = + ecma_regexp_replace_helper_fast (&replace_ctx, (ecma_extended_object_t *) this_obj_p, string_p, replace_arg); + + goto cleanup_replace; + } + } + + results_p = ecma_new_collection (); + + while (true) + { + /* 13.a */ + if (ecma_op_is_callable (result)) + { + ecma_object_t *const function_p = ecma_get_object_from_value (result); + + ecma_value_t arguments[] = { ecma_make_string_value (string_p) }; + result = ecma_op_function_call (function_p, this_arg, arguments, 1); + + ecma_deref_object (function_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + if (!ecma_is_value_object (result) && !ecma_is_value_null (result)) + { + ecma_free_value (result); + result = ecma_raise_type_error (ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL); + goto cleanup_results; + } + } + else + { + ecma_free_value (result); + + if (!ecma_object_class_is (this_obj_p, ECMA_OBJECT_CLASS_REGEXP)) + { + result = ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP_OBJECT); + goto cleanup_results; + } + + result = ecma_regexp_exec_helper (this_obj_p, string_p); + } + + /* 13.c */ + if (ecma_is_value_null (result)) + { + break; + } + + /* 13.d.i */ + ecma_collection_push_back (results_p, result); + + if ((replace_ctx.flags & RE_FLAG_GLOBAL) == 0) + { + break; + } + + /* 13.d.iii.1 */ + result = ecma_op_object_get_by_index (ecma_get_object_from_value (result), 0); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + ecma_string_t *match_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (match_str_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_results; + } + + const bool is_empty = ecma_string_is_empty (match_str_p); + ecma_deref_ecma_string (match_str_p); + + /* 13.d.iii.3 */ + if (is_empty) + { + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + ecma_value_t last_index = result; + + ecma_length_t index; + result = ecma_op_to_length (last_index, &index); + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + index = ecma_op_advance_string_index (string_p, index, (replace_ctx.flags & RE_FLAG_UNICODE) != 0); + last_index = ecma_make_length_value (index); + + /* 10.d.iii.3.c */ + result = ecma_op_object_put (this_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index, true); + + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + } + + result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_EXEC); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_results; + } + } + + string_flags = ECMA_STRING_FLAG_IS_ASCII; + replace_ctx.string_p = ecma_string_get_chars (string_p, &(replace_ctx.string_size), NULL, NULL, &string_flags); + + /* 14. */ + replace_ctx.builder = ecma_stringbuilder_create (); + replace_ctx.matched_p = NULL; + replace_ctx.capture_count = 0; + index = 0; + + /* 15. */ + source_position_p = (lit_utf8_byte_t*) replace_ctx.string_p; + string_end_p = (lit_utf8_byte_t*) replace_ctx.string_p + replace_ctx.string_size; + + /* 16. */ + for (ecma_value_t *current_p = results_p->buffer_p; current_p < results_p->buffer_p + results_p->item_count; + current_p++) + { + /* 16.a */ + ecma_object_t *current_object_p = ecma_get_object_from_value (*current_p); + + ecma_length_t capture_count; + result = ecma_op_object_get_length (current_object_p, &capture_count); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + /* 16.c */ + capture_count = (capture_count > 0) ? capture_count - 1 : capture_count; + + /* 16.d */ + result = ecma_op_object_get_by_index (current_object_p, 0); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + ecma_string_t *matched_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + /* 16.e */ + if (matched_str_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + /* 16.g */ + result = ecma_op_object_get_by_magic_id (current_object_p, LIT_MAGIC_STRING_INDEX); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_ecma_string (matched_str_p); + goto cleanup_builder; + } + + const ecma_value_t index_value = result; + + ecma_number_t position_num; + result = ecma_op_to_integer (index_value, &position_num); + ecma_free_value (index_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_deref_ecma_string (matched_str_p); + goto cleanup_builder; + } + + /* 16.i */ + lit_utf8_size_t position = JERRY_MIN ((lit_utf8_size_t) JERRY_MAX (position_num, 0.0f), string_length); + + /* 16.k */ + ecma_collection_t *arguments_p = ecma_new_collection (); + ecma_collection_push_back (arguments_p, ecma_make_string_value (matched_str_p)); + + /* 16.j, l */ + ecma_length_t n = 1; + while (n <= capture_count) + { + result = ecma_op_object_get_by_index (current_object_p, n); + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_collection_free (arguments_p); + goto cleanup_builder; + } + + /* 16.l.iii */ + if (!ecma_is_value_undefined (result)) + { + ecma_string_t *capture_str_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (capture_str_p == NULL) + { + ecma_collection_free (arguments_p); + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + result = ecma_make_string_value (capture_str_p); + } + + /* 16.l.iv */ + ecma_collection_push_back (arguments_p, result); + n++; + } + + const bool should_replace = (position >= index); + /* 16.p */ + if (should_replace) + { + const lit_utf8_byte_t *match_position_p; + const lit_utf8_size_t matched_str_size = ecma_string_get_size (matched_str_p); + const lit_utf8_size_t matched_str_length = ecma_string_get_length (matched_str_p); + + if (string_flags & ECMA_STRING_FLAG_IS_ASCII) + { + match_position_p = replace_ctx.string_p + position; + } + else + { + match_position_p = source_position_p; + lit_utf8_size_t distance = position - index; + while (distance--) + { + lit_utf8_incr (&match_position_p); + } + } + + ecma_stringbuilder_append_raw (&replace_ctx.builder, + source_position_p, + (lit_utf8_size_t) (match_position_p - source_position_p)); + replace_ctx.match_byte_pos = (lit_utf8_size_t) (match_position_p - replace_ctx.string_p); + + if ((string_flags & ECMA_STRING_FLAG_IS_ASCII) && matched_str_size == matched_str_length) + { + source_position_p = (lit_utf8_byte_t*) JERRY_MIN (match_position_p + matched_str_size, string_end_p); + } + else + { + lit_utf8_size_t code_unit_count = matched_str_length; + + while (code_unit_count-- > 0 && JERRY_LIKELY (match_position_p < string_end_p)) + { + lit_utf8_incr (&match_position_p); + } + + source_position_p = (lit_utf8_byte_t*) match_position_p; + } + + index = JERRY_MIN (position + matched_str_length, string_length); + } + + /* 16.m */ + if (replace_ctx.replace_str_p == NULL) + { + /* 16.m.i-ii. + * arguments_p already contains <> */ + + /* 16.m.iii */ + ecma_collection_push_back (arguments_p, ecma_make_uint32_value (position)); + ecma_ref_ecma_string (string_p); + ecma_collection_push_back (arguments_p, ecma_make_string_value (string_p)); + + result = ecma_op_function_call (ecma_get_object_from_value (replace_arg), + ECMA_VALUE_UNDEFINED, + arguments_p->buffer_p, + arguments_p->item_count); + + ecma_collection_free (arguments_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto cleanup_builder; + } + + /* 16.m.v */ + ecma_string_t *const replace_result_p = ecma_op_to_string (result); + ecma_free_value (result); + + if (replace_result_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto cleanup_builder; + } + + /* 16.m/p */ + if (should_replace) + { + ecma_stringbuilder_append (&replace_ctx.builder, replace_result_p); + } + + ecma_deref_ecma_string (replace_result_p); + } + else + { + /* 16.n/p */ + if (should_replace) + { + replace_ctx.u.collection_p = arguments_p; + ecma_builtin_replace_substitute (&replace_ctx); + } + + ecma_collection_free (arguments_p); + } + } + + /* 18. */ + JERRY_ASSERT (index <= string_length); + ecma_stringbuilder_append_raw (&(replace_ctx.builder), + source_position_p, + (lit_utf8_size_t) (string_end_p - source_position_p)); + + result = ecma_make_string_value (ecma_stringbuilder_finalize (&replace_ctx.builder)); + goto cleanup_chars; + +cleanup_builder: + ecma_stringbuilder_destroy (&replace_ctx.builder); + +cleanup_chars: + if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + jmem_heap_free_block ((void *) replace_ctx.string_p, replace_ctx.string_size); + } + +cleanup_results: + ecma_collection_free (results_p); + +cleanup_replace: + if (replace_ctx.replace_str_p != NULL) + { + ecma_deref_ecma_string (replace_ctx.replace_str_p); + } + +cleanup_string: + ecma_deref_ecma_string (string_p); + + return result; +} /* ecma_regexp_replace_helper */ + +/** + * Helper function for RegExp based matching + * + * See also: + * String.prototype.match + * RegExp.prototype[@@match] + * + * @return ecma_value_t + */ +ecma_value_t +ecma_regexp_match_helper (ecma_value_t this_arg, /**< this argument */ + ecma_value_t string_arg) /**< source string */ +{ + if (!ecma_is_value_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT); + } + + ecma_string_t *str_p = ecma_op_to_string (string_arg); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); + + ecma_value_t global_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_GLOBAL); + + if (ECMA_IS_VALUE_ERROR (global_value)) + { + ecma_deref_ecma_string (str_p); + return global_value; + } + + bool global = ecma_op_to_boolean (global_value); + + ecma_free_value (global_value); + + if (!global) + { + ecma_value_t result = ecma_op_regexp_exec (this_arg, str_p); + ecma_deref_ecma_string (str_p); + return result; + } + + ecma_value_t full_unicode_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_UNICODE); + + if (ECMA_IS_VALUE_ERROR (full_unicode_value)) + { + ecma_deref_ecma_string (str_p); + return full_unicode_value; + } + + bool full_unicode = ecma_op_to_boolean (full_unicode_value); + + ecma_free_value (full_unicode_value); + + ecma_value_t set_status = + ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), ecma_make_uint32_value (0), true); + + if (ECMA_IS_VALUE_ERROR (set_status)) + { + ecma_deref_ecma_string (str_p); + return set_status; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_object_t *result_array_p = ecma_op_new_array_object (0); + uint32_t n = 0; + + while (true) + { + ecma_value_t result_value = ecma_op_regexp_exec (this_arg, str_p); + + if (ECMA_IS_VALUE_ERROR (result_value)) + { + goto result_cleanup; + } + + if (ecma_is_value_null (result_value)) + { + if (n == 0) + { + ret_value = ECMA_VALUE_NULL; + goto result_cleanup; + } + + ecma_deref_ecma_string (str_p); + return ecma_make_object_value (result_array_p); + } + + ecma_object_t *result_value_p = ecma_get_object_from_value (result_value); + ecma_value_t match_value = ecma_op_object_get_by_index (result_value_p, 0); + + ecma_deref_object (result_value_p); + + if (ECMA_IS_VALUE_ERROR (match_value)) + { + goto result_cleanup; + } + + ecma_string_t *match_str_p = ecma_op_to_string (match_value); + ecma_free_value (match_value); + + if (JERRY_UNLIKELY (match_str_p == NULL)) + { + goto result_cleanup; + } + + ecma_value_t new_prop = ecma_builtin_helper_def_prop_by_index (result_array_p, + n, + ecma_make_string_value (match_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_prop)); + + const bool is_match_empty = ecma_string_is_empty (match_str_p); + ecma_deref_ecma_string (match_str_p); + + if (is_match_empty) + { + ecma_value_t last_index = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); + + if (ECMA_IS_VALUE_ERROR (last_index)) + { + goto result_cleanup; + } + + ecma_length_t index; + ecma_value_t length_value = ecma_op_to_length (last_index, &index); + + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (length_value)) + { + goto result_cleanup; + } + + index = ecma_op_advance_string_index (str_p, index, full_unicode); + + last_index = ecma_make_length_value (index); + ecma_value_t next_set_status = + ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index, true); + + ecma_free_value (last_index); + + if (ECMA_IS_VALUE_ERROR (next_set_status)) + { + goto result_cleanup; + } + } + + n++; + } + +result_cleanup: + ecma_deref_ecma_string (str_p); + ecma_deref_object (result_array_p); + return ret_value; +} /* ecma_regexp_match_helper */ + +/** + * RegExpExec operation + * + * See also: + * ECMA-262 v6.0, 21.2.5.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_op_regexp_exec (ecma_value_t this_arg, /**< this argument */ + ecma_string_t *str_p) /**< input string */ +{ + ecma_object_t *arg_obj_p = ecma_get_object_from_value (this_arg); + + ecma_value_t exec = ecma_op_object_get_by_magic_id (arg_obj_p, LIT_MAGIC_STRING_EXEC); + + if (ECMA_IS_VALUE_ERROR (exec)) + { + return exec; + } + + if (ecma_op_is_callable (exec)) + { + ecma_object_t *function_p = ecma_get_object_from_value (exec); + ecma_value_t arguments[] = { ecma_make_string_value (str_p) }; + + ecma_value_t result = ecma_op_function_call (function_p, this_arg, arguments, 1); + + ecma_deref_object (function_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (!ecma_is_value_object (result) && !ecma_is_value_null (result)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL); + } + + return result; + } + else + { + ecma_free_value (exec); + } + + if (!ecma_object_is_regexp_object (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_REG_EXP); + } + + return ecma_regexp_exec_helper (arg_obj_p, str_p); +} /* ecma_op_regexp_exec */ + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.h new file mode 100644 index 00000000..89815897 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.h @@ -0,0 +1,191 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_REGEXP_OBJECT_H +#define ECMA_REGEXP_OBJECT_H + +#include "ecma-globals.h" + +#include "re-compiler.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaregexpobject ECMA RegExp object related routines + * @{ + */ + +/** + * RegExp flags + * Note: + * This enum has to be kept in sync with jerry_regexp_flags_t. + */ +typedef enum +{ + RE_FLAG_EMPTY = 0u, /* Empty RegExp flags */ + RE_FLAG_GLOBAL = (1u << 1), /**< ECMA-262 v5, 15.10.7.2 */ + RE_FLAG_IGNORE_CASE = (1u << 2), /**< ECMA-262 v5, 15.10.7.3 */ + RE_FLAG_MULTILINE = (1u << 3), /**< ECMA-262 v5, 15.10.7.4 */ + RE_FLAG_STICKY = (1u << 4), /**< ECMA-262 v6, 21.2.5.12 */ + RE_FLAG_UNICODE = (1u << 5), /**< ECMA-262 v6, 21.2.5.15 */ + RE_FLAG_DOTALL = (1u << 6) /**< ECMA-262 v9, 21.2.5.3 */ + + /* Bits from bit 13 is reserved for function types (see CBC_FUNCTION_TYPE_SHIFT). */ +} ecma_regexp_flags_t; + +/** + * Class escapes + */ +typedef enum +{ + RE_ESCAPE__START, /**< escapes start */ + RE_ESCAPE_DIGIT = RE_ESCAPE__START, /**< digit */ + RE_ESCAPE_NOT_DIGIT, /**< not digit */ + RE_ESCAPE_WORD_CHAR, /**< word char */ + RE_ESCAPE_NOT_WORD_CHAR, /**< not word char */ + RE_ESCAPE_WHITESPACE, /**< whitespace */ + RE_ESCAPE_NOT_WHITESPACE, /**< not whitespace */ + RE_ESCAPE__COUNT, /**< escape count */ +} ecma_class_escape_t; + +/** + * Character class flags escape count mask size. + */ +#define RE_CLASS_ESCAPE_COUNT_MASK_SIZE (3u) + +/** + * Character class flags escape count mask. + */ +#define RE_CLASS_ESCAPE_COUNT_MASK ((1 << RE_CLASS_ESCAPE_COUNT_MASK_SIZE) - 1u) + +/** + * Character class flags that are present in the upper bits of the class flags byte, while the 3 least significant bits + * hold a value that contains the number of class escapes present in the character class. + */ +typedef enum +{ + RE_CLASS_HAS_CHARS = (1 << 5), /**< contains individual characters */ + RE_CLASS_HAS_RANGES = (1 << 6), /**< contains character ranges */ + RE_CLASS_INVERT = (1 << 7), /**< inverted */ +} ecma_char_class_flags_t; + +/** + * Structure for matching capturing groups and storing their result + */ +typedef struct +{ + const lit_utf8_byte_t *begin_p; /**< capture start pointer */ + const lit_utf8_byte_t *end_p; /**< capture end pointer */ + const uint8_t *bc_p; /**< group bytecode pointer */ + uint32_t iterator; /**< iteration counter */ + uint32_t subcapture_count; /**< number of nested capturing groups */ +} ecma_regexp_capture_t; + +/** + * Structure for matching non-capturing groups + */ +typedef struct +{ + const lit_utf8_byte_t *begin_p; /**< substring start pointer */ + const uint8_t *bc_p; /**< group bytecode pointer */ + uint32_t iterator; /**< iteration counter */ + uint32_t subcapture_start; /**< first nested capturing group index */ + uint32_t subcapture_count; /**< number of nested capturing groups */ +} ecma_regexp_non_capture_t; + +/** + * Check if an ecma_regexp_capture_t contains a defined capture + */ +#define ECMA_RE_IS_CAPTURE_DEFINED(c) ((c)->begin_p != NULL) + +ecma_value_t ecma_regexp_get_capture_value (const ecma_regexp_capture_t *const capture_p); + +#if (JERRY_STACK_LIMIT != 0) +/** + * Value used ase result when stack limit is reached + */ +#define ECMA_RE_OUT_OF_STACK ((const lit_utf8_byte_t *) UINTPTR_MAX) + +/** + * Checks if the stack limit has been reached during regexp matching + */ +#define ECMA_RE_STACK_LIMIT_REACHED(p) (JERRY_UNLIKELY (p == ECMA_RE_OUT_OF_STACK)) +#else /* JERRY_STACK_LIMIT == 0 */ +#define ECMA_RE_STACK_LIMIT_REACHED(p) (false) +#endif /* JERRY_STACK_LIMIT != 0 */ + +/** + * Offset applied to qmax when encoded into the bytecode. + * + * It's common for qmax to be Infinity, which is represented a UINT32_MAX. By applying the offset we are able to store + * it in a single byte az zero. + */ +#define RE_QMAX_OFFSET 1 + +/** + * RegExp executor context + */ +typedef struct +{ + const lit_utf8_byte_t *input_start_p; /**< start of input string */ + const lit_utf8_byte_t *input_end_p; /**< end of input string */ + uint32_t captures_count; /**< number of capture groups */ + uint32_t non_captures_count; /**< number of non-capture groups */ + ecma_regexp_capture_t *captures_p; /**< capturing groups */ + ecma_regexp_non_capture_t *non_captures_p; /**< non-capturing groups */ + uint16_t flags; /**< RegExp flags */ + uint8_t char_size; /**< size of encoded characters */ +} ecma_regexp_ctx_t; + +/** + * RegExpStringIterator object internal slots + * + * See also: + * ECMA-262 v11, 21.2.7.2 + */ +typedef struct +{ + ecma_extended_object_t header; /**< extended object part */ + ecma_value_t iterating_regexp; /**< [[IteratingRegExp]] internal slot */ + ecma_value_t iterated_string; /**< [[IteratedString]] internal slot */ +} ecma_regexp_string_iterator_t; + +lit_code_point_t ecma_regexp_unicode_advance (const lit_utf8_byte_t **str_p, const lit_utf8_byte_t *end_p); +ecma_object_t *ecma_op_regexp_alloc (ecma_object_t *new_target_obj_p); +ecma_value_t ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, ecma_string_t *input_string_p); +ecma_string_t *ecma_regexp_read_pattern_str_helper (ecma_value_t pattern_arg); +lit_code_point_t ecma_regexp_canonicalize_char (lit_code_point_t ch, bool unicode); +ecma_value_t ecma_regexp_parse_flags (ecma_string_t *flags_str_p, uint16_t *flags_p); +void ecma_regexp_create_and_initialize_props (ecma_object_t *re_object_p, ecma_string_t *source_p, uint16_t flags); +ecma_value_t ecma_regexp_replace_helper (ecma_value_t this_arg, ecma_value_t string_arg, ecma_value_t replace_arg); +ecma_value_t ecma_regexp_search_helper (ecma_value_t regexp_arg, ecma_value_t string_arg); +ecma_value_t ecma_regexp_split_helper (ecma_value_t this_arg, ecma_value_t string_arg, ecma_value_t limit_arg); +ecma_value_t ecma_regexp_match_helper (ecma_value_t this_arg, ecma_value_t string_arg); + +ecma_value_t ecma_op_regexp_exec (ecma_value_t this_arg, ecma_string_t *str_p); + +ecma_value_t ecma_op_create_regexp_from_bytecode (ecma_object_t *regexp_obj_p, re_compiled_code_t *bc_p); +ecma_value_t +ecma_op_create_regexp_from_pattern (ecma_object_t *regexp_obj_p, ecma_value_t pattern_value, ecma_value_t flags_value); +ecma_value_t ecma_op_create_regexp_with_flags (ecma_object_t *regexp_obj_p, ecma_value_t pattern_value, uint16_t flags); +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !ECMA_REGEXP_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.cpp new file mode 100644 index 00000000..658af2de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.cpp @@ -0,0 +1,161 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-shared-arraybuffer-object.h" + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasharedarraybufferobject ECMA SharedArrayBuffer object related routines + * @{ + */ + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +/** + * Creating SharedArrayBuffer objects based on the array length + * + * @return new SharedArrayBuffer object + */ +ecma_object_t * +ecma_shared_arraybuffer_new_object (uint32_t length) /**< length of the SharedArrayBuffer */ +{ + if (length > 0) + { + return ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, length); + } + + return ecma_arraybuffer_create_object (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, length); +} /* ecma_shared_arraybuffer_new_object */ + +/** + * SharedArrayBuffer object creation operation. + * + * See also: ES11 24.1.1.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_shared_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that + * are passed to String constructor */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p), + ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE); + + if (proto_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t length_num = 0; + + if (arguments_list_len > 0) + { + if (ecma_is_value_number (arguments_list_p[0])) + { + length_num = ecma_get_number_from_value (arguments_list_p[0]); + } + else + { + ecma_value_t to_number_value = ecma_op_to_number (arguments_list_p[0], &length_num); + + if (ECMA_IS_VALUE_ERROR (to_number_value)) + { + ecma_deref_object (proto_p); + return to_number_value; + } + } + + if (ecma_number_is_nan (length_num)) + { + length_num = 0; + } + + const uint32_t maximum_size_in_byte = UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1; + + if (length_num <= -1.0 || length_num > (ecma_number_t) maximum_size_in_byte + 0.5) + { + ecma_deref_object (proto_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_SHARED_ARRAYBUFFER_LENGTH); + } + } + + uint32_t length_uint32 = ecma_number_to_uint32 (length_num); + ecma_object_t *shared_array_buffer = ecma_shared_arraybuffer_new_object (length_uint32); + ECMA_SET_NON_NULL_POINTER (shared_array_buffer->u2.prototype_cp, proto_p); + ecma_deref_object (proto_p); + + return ecma_make_object_value (shared_array_buffer); +} /* ecma_op_create_shared_arraybuffer_object */ + +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ + +/** + * Helper function: check if the target is SharedArrayBuffer + * + * See also: ES11 24.1.1.4 + * + * @return true - if value is a SharedArrayBuffer object + * false - otherwise + */ +bool +ecma_is_shared_arraybuffer (ecma_value_t target) /**< the target value */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + return (ecma_is_value_object (target) + && ecma_object_class_is (ecma_get_object_from_value (target), ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (target); + return false; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* ecma_is_shared_arraybuffer */ + +/** + * Helper function: check if the target is SharedArrayBuffer Object + * + * @return true - if value is a SharedArrayBuffer object + * false - otherwise + */ +bool +ecma_object_is_shared_arraybuffer (ecma_object_t *object_p) /**< the target object */ +{ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + return ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER); +#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */ + JERRY_UNUSED (object_p); + return false; +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +} /* ecma_object_is_shared_arraybuffer */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.h new file mode 100644 index 00000000..65b480ed --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-shared-arraybuffer-object.h @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_SHARED_ARRAYBUFFER_OBJECT_H +#define ECMA_SHARED_ARRAYBUFFER_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasharedarraybufferobject ECMA SharedArrayBuffer object related routines + * @{ + */ + +#if JERRY_BUILTIN_SHAREDARRAYBUFFER + +ecma_value_t ecma_op_create_shared_arraybuffer_object (const ecma_value_t *, uint32_t); + +/** + * Helper functions for SharedArrayBuffer. + */ +ecma_object_t *ecma_shared_arraybuffer_new_object (uint32_t lengh); +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +bool ecma_is_shared_arraybuffer (ecma_value_t val); +bool ecma_object_is_shared_arraybuffer (ecma_object_t *val); + +/** + * @} + * @} + */ + +#endif /* !ECMA_SHARED_ARRAYBUFFER_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.cpp new file mode 100644 index 00000000..95b78c9a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.cpp @@ -0,0 +1,140 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-string-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmastringobject ECMA String object related routines + * @{ + */ + +/** + * String object creation operation. + * + * See also: ECMA-262 v5, 15.5.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that + are passed to String constructor */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t prim_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + + if (arguments_list_len > 0) + { + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + prim_value = ecma_make_string_value (str_p); + } + + ecma_builtin_id_t proto_id; +#if JERRY_BUILTIN_STRING + proto_id = ECMA_BUILTIN_ID_STRING_PROTOTYPE; +#else /* !JERRY_BUILTIN_STRING */ + proto_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; +#endif /* JERRY_BUILTIN_STRING */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id); + + ecma_object_t *new_target = JERRY_CONTEXT (current_new_target_p); + if (new_target) + { + prototype_obj_p = ecma_op_get_prototype_from_constructor (new_target, proto_id); + if (JERRY_UNLIKELY (prototype_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_STRING; + ext_object_p->u.cls.u3.value = prim_value; + + if (new_target) + { + ecma_deref_object (prototype_obj_p); + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_string_object */ + +/** + * List names of a String object's lazy instantiated properties + */ +void +ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_get_object_base_type (obj_p) == ECMA_OBJECT_BASE_TYPE_CLASS); + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + JERRY_ASSERT (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_STRING); + + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.cls.u3.value); + + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + + for (lit_utf8_size_t i = 0; i < length; i++) + { + ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); + + /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ + ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); + } + + prop_counter_p->array_index_named_props += length; + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } +} /* ecma_op_string_list_lazy_property_names */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.h new file mode 100644 index 00000000..0ebb2c12 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-string-object.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_STRING_OBJECT_H +#define ECMA_STRING_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmastringobject ECMA String object related routines + * @{ + */ + +ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); + +void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +/** + * @} + * @} + */ + +#endif /* !ECMA_STRING_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.cpp new file mode 100644 index 00000000..adf84367 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.cpp @@ -0,0 +1,177 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-symbol-object.h" + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" + +#include "lit-char-helpers.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasymbolobject ECMA Symbol object related routines + * @{ + */ + +/** + * Symbol creation operation. + * + * See also: ECMA-262 v6, 6.1.5.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_symbol (const ecma_value_t *arguments_list_p, /**< list of arguments */ + uint32_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t string_desc; + + /* 1-3. */ + if (arguments_list_len == 0 || ecma_is_value_undefined (arguments_list_p[0])) + { + string_desc = ECMA_VALUE_UNDEFINED; + } + else + { + ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]); + + /* 4. */ + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + string_desc = ecma_make_string_value (str_p); + } + + /* 5. */ + return ecma_make_symbol_value (ecma_new_symbol_from_descriptor_string (string_desc)); +} /* ecma_op_create_symbol */ + +/** + * Symbol object creation operation. + * + * See also: ECMA-262 v6, 19.4.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_symbol_object (const ecma_value_t value) /**< symbol value */ +{ + JERRY_ASSERT (ecma_is_value_symbol (value)); + + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE); + ecma_object_t *object_p = + ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_SYMBOL; + ext_object_p->u.cls.u3.value = ecma_copy_value (value); + + return ecma_make_object_value (object_p); +} /* ecma_op_create_symbol_object */ + +/** + * Get the symbol descriptor ecma-string from an ecma-symbol + * + * @return pointer to ecma-string descriptor + */ +ecma_value_t +ecma_get_symbol_description (ecma_string_t *symbol_p) /**< ecma-symbol */ +{ + JERRY_ASSERT (symbol_p != NULL); + JERRY_ASSERT (ecma_prop_name_is_symbol (symbol_p)); + + return ((ecma_extended_string_t *) symbol_p)->u.symbol_descriptor; +} /* ecma_get_symbol_description */ + +/** + * Get the descriptive string of the Symbol. + * + * See also: ECMA-262 v6, 19.4.3.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_get_symbol_descriptive_string (ecma_value_t symbol_value) /**< symbol to stringify */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_symbol (symbol_value)); + + /* 2 - 3. */ + ecma_string_t *symbol_p = ecma_get_symbol_from_value (symbol_value); + ecma_value_t string_desc = ecma_get_symbol_description (symbol_p); + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) ("Symbol("), 7); + + if (!ecma_is_value_undefined (string_desc)) + { + ecma_string_t *string_desc_p = ecma_get_string_from_value (string_desc); + ecma_stringbuilder_append (&builder, string_desc_p); + } + + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_RIGHT_PAREN); + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_get_symbol_descriptive_string */ + +/** + * thisSymbolValue abstract operation + * + * See also: + * ECMA-262 v11, 19.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_symbol_this_value (ecma_value_t this_arg) /**< this argument value */ +{ + /* 1. */ + if (ecma_is_value_symbol (this_arg)) + { + return this_arg; + } + + /* 2. */ + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_SYMBOL)) + { + return ((ecma_extended_object_t *) object_p)->u.cls.u3.value; + } + } + + /* 3. */ + return ecma_raise_type_error (ECMA_ERR_ARGUMENT_THIS_NOT_SYMBOL); +} /* ecma_symbol_this_value */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.h new file mode 100644 index 00000000..4f27e02a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-symbol-object.h @@ -0,0 +1,45 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_SYMBOL_H +#define ECMA_SYMBOL_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasymbolobject ECMA Symbol object related routines + * @{ + */ + +ecma_value_t ecma_op_create_symbol (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); + +ecma_value_t ecma_op_create_symbol_object (const ecma_value_t value); + +bool ecma_prop_name_is_symbol (ecma_string_t *string_p); + +ecma_value_t ecma_get_symbol_description (ecma_string_t *symbol_p); + +ecma_value_t ecma_symbol_this_value (ecma_value_t this_arg); + +ecma_value_t ecma_get_symbol_descriptive_string (ecma_value_t symbol_value); + +/** + * @} + * @} + */ + +#endif /* !ECMA_SYMBOL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.cpp b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.cpp new file mode 100644 index 00000000..d3500350 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.cpp @@ -0,0 +1,2119 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-typedarray-object.h" + +#include + +#include "ecma-arraybuffer-object.h" +#include "ecma-big-uint.h" +#include "ecma-bigint.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers-number.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-shared-arraybuffer-object.h" + +#include "jcontext.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmatypedarrayobject ECMA TypedArray object related routines + * @{ + */ + +/** + * Read and copy a number from a given buffer to a value. + **/ +#define ECMA_TYPEDARRAY_GET_ELEMENT(src_p, num, type) \ + do \ + { \ + if (JERRY_LIKELY ((((uintptr_t) (src_p)) & (sizeof (type) - 1)) == 0)) \ + { \ + num = *(type *) ((void *) src_p); \ + } \ + else \ + { \ + memcpy (&num, (void *) src_p, sizeof (type)); \ + } \ + } while (0) + +/** + * Copy a number from a value to the given buffer + **/ +#define ECMA_TYPEDARRAY_SET_ELEMENT(src_p, num, type) \ + do \ + { \ + if (JERRY_LIKELY ((((uintptr_t) (src_p)) & (sizeof (type) - 1)) == 0)) \ + { \ + *(type *) ((void *) src_p) = num; \ + } \ + else \ + { \ + memcpy ((void *) src_p, &num, sizeof (type)); \ + } \ + } while (0) + +/** + * Read an int8_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_int8_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + int8_t num = (int8_t) *src; + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_int8_element */ + +/** + * Read an uint8_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_uint8_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint8_t num = (uint8_t) *src; + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_uint8_element */ + +/** + * Read an int16_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_int16_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + int16_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, int16_t); + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_int16_element */ + +/** + * Read an uint16_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_uint16_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint16_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint16_t); + return ecma_make_integer_value (num); +} /* ecma_typedarray_get_uint16_element */ + +/** + * Read an int32_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_int32_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + int32_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, int32_t); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_int32_element */ + +/** + * Read an uint32_t value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_uint32_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint32_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint32_t); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_uint32_element */ + +/** + * Read a float value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_float_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + float num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, float); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_float_element */ + +/** + * Read a double value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_double_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + double num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, double); + return ecma_make_number_value (num); +} /* ecma_typedarray_get_double_element */ + +#if JERRY_BUILTIN_BIGINT +/** + * Read a bigint64 value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_bigint64_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint64_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint64_t); + bool sign = (num >> 63) != 0; + + if (sign) + { + num = (uint64_t) (-(int64_t) num); + } + + return ecma_bigint_create_from_digits (&num, 1, sign); +} /* ecma_typedarray_get_bigint64_element */ + +/** + * Read a biguint64 value from the given arraybuffer + */ +static ecma_value_t +ecma_typedarray_get_biguint64_element (lit_utf8_byte_t *src) /**< the location in the internal arraybuffer */ +{ + uint64_t num; + ECMA_TYPEDARRAY_GET_ELEMENT (src, num, uint64_t); + return ecma_bigint_create_from_digits (&num, 1, false); +} /* ecma_typedarray_get_biguint64_element */ +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Normalize the given ecma_number_t to an uint32_t value + */ +static uint32_t +ecma_typedarray_setter_number_to_uint32 (ecma_number_t value) /**< the number value to normalize */ +{ + uint32_t uint32_value = 0; + + if (!ecma_number_is_nan (value) && !ecma_number_is_infinity (value)) + { + bool is_negative = false; + + if (value < 0) + { + is_negative = true; + value = -value; + } + + if (value > ((ecma_number_t) 0xffffffff)) + { + value = (ecma_number_t) (fmod (value, (ecma_number_t) 0x100000000)); + } + + uint32_value = (uint32_t) value; + + if (is_negative) + { + uint32_value = (uint32_t) (-(int32_t) uint32_value); + } + } + + return uint32_value; +} /* ecma_typedarray_setter_number_to_uint32 */ + +/** + * Write an int8_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_int8_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + int8_t num = (int8_t) ecma_typedarray_setter_number_to_uint32 (result_num); + *dst_p = (lit_utf8_byte_t) num; + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_int8_element */ + +/** + * Write an uint8_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint8_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint8_t num = (uint8_t) ecma_typedarray_setter_number_to_uint32 (result_num); + *dst_p = (lit_utf8_byte_t) num; + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint8_element */ + +/** + * Write an uint8_t clamped value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint8_clamped_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint8_t clamped; + + if (result_num > 255) + { + clamped = 255; + } + else if (result_num <= 0) + { + clamped = 0; + } + else + { + clamped = (uint8_t) result_num; + + if (clamped + 0.5 < result_num || (clamped + 0.5 == result_num && (clamped % 2) == 1)) + { + clamped++; + } + } + + *dst_p = (lit_utf8_byte_t) clamped; + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint8_clamped_element */ + +/** + * Write an int16_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_int16_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + int16_t num = (int16_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, int16_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_int16_element */ + +/** + * Write an uint8_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint16_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint16_t num = (uint16_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, uint16_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint16_element */ + +/** + * Write an int32_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_int32_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + int32_t num = (int32_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, int32_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_int32_element */ + +/** + * Write an uint32_t value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_uint32_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t resut_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &resut_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + uint32_t num = (uint32_t) ecma_typedarray_setter_number_to_uint32 (resut_num); + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, uint32_t); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_uint32_element */ + +/** + * Write a float value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_float_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + float num = (float) result_num; + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, float); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_float_element */ + +#if JERRY_NUMBER_TYPE_FLOAT64 +/** + * Write a double value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToNumber operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_double_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the number value to set */ +{ + ecma_number_t result_num; + ecma_value_t to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + + double num = (double) result_num; + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, double); + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_double_element */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +#if JERRY_BUILTIN_BIGINT +/** + * Write a bigint64/biguint64 value into the given arraybuffer + * + * @return ECMA_VALUE_ERROR - if the ToBigInt operation fails + * ECMA_VALUE_TRUE - otherwise + */ +static ecma_value_t +ecma_typedarray_set_bigint_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_value_t value) /**< the bigint value to set */ +{ + ecma_value_t bigint = ecma_bigint_to_bigint (value, false); + + if (ECMA_IS_VALUE_ERROR (bigint)) + { + return bigint; + } + + uint64_t num; + bool sign; + ecma_bigint_get_digits_and_sign (bigint, &num, 1, &sign); + + if (sign) + { + num = (uint64_t) (-(int64_t) num); + } + + ECMA_TYPEDARRAY_SET_ELEMENT (dst_p, num, uint64_t); + + ecma_free_value (bigint); + + return ECMA_VALUE_TRUE; +} /* ecma_typedarray_set_bigint_element */ +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Builtin id of the first %TypedArray% builtin routine intrinsic object + */ +#define ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_INT8ARRAY + +#if JERRY_BUILTIN_BIGINT +/** + * Builtin id of the last %TypedArray% builtin routine intrinsic object + */ +#define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_BIGUINT64ARRAY +#elif !JERRY_BUILTIN_BIGINT && JERRY_NUMBER_TYPE_FLOAT64 +/** + * Builtin id of the last %TypedArray% builtin routine intrinsic object + */ +#define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_FLOAT64ARRAY +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +/** + * Builtin id of the last %TypedArray% builtin routine intrinsic object + */ +#define ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID ECMA_BUILTIN_ID_FLOAT32ARRAY +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Builtin id of the first %TypedArray% builtin prototype intrinsic object + */ +#define ECMA_FIRST_TYPEDARRAY_BUILTIN_PROTOTYPE_ID ECMA_BUILTIN_ID_INT8ARRAY_PROTOTYPE + +/** + * List of typedarray getters based on their builtin id + */ +static const ecma_typedarray_getter_fn_t ecma_typedarray_getters[] = { + ecma_typedarray_get_int8_element, /**< Int8Array */ + ecma_typedarray_get_uint8_element, /**< Uint8Array */ + ecma_typedarray_get_uint8_element, /**< Uint8ClampedArray */ + ecma_typedarray_get_int16_element, /**< Int16Array */ + ecma_typedarray_get_uint16_element, /**< Int32Array */ + ecma_typedarray_get_int32_element, /**< Uint32Array */ + ecma_typedarray_get_uint32_element, /**< Uint32Array */ + ecma_typedarray_get_float_element, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + ecma_typedarray_get_double_element, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ecma_typedarray_get_bigint64_element, /**< BigInt64Array*/ + ecma_typedarray_get_biguint64_element, /**< BigUint64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * List of typedarray setters based on their builtin id + */ +static const ecma_typedarray_setter_fn_t ecma_typedarray_setters[] = { + ecma_typedarray_set_int8_element, /**< Int8Array */ + ecma_typedarray_set_uint8_element, /**< Uint8Array */ + ecma_typedarray_set_uint8_clamped_element, /**< Uint8ClampedArray */ + ecma_typedarray_set_int16_element, /**< Int16Array */ + ecma_typedarray_set_uint16_element, /**< Int32Array */ + ecma_typedarray_set_int32_element, /**< Uint32Array */ + ecma_typedarray_set_uint32_element, /**< Uint32Array */ + ecma_typedarray_set_float_element, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + ecma_typedarray_set_double_element, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + ecma_typedarray_set_bigint_element, /**< BigInt64Array */ + ecma_typedarray_set_bigint_element, /**< BigUInt64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * List of typedarray element shift sizes based on their builtin id + */ +static const uint8_t ecma_typedarray_element_shift_sizes[] = { + 0, /**< Int8Array */ + 0, /**< Uint8Array */ + 0, /**< Uint8ClampedArray */ + 1, /**< Int16Array */ + 1, /**< Uint16Array */ + 2, /**< Int32Array */ + 2, /**< Uint32Array */ + 2, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + 3, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + 3, /**< BigInt64Array */ + 3, /**< BigUInt64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * List of typedarray class magic strings based on their builtin id + */ +static const uint16_t ecma_typedarray_magic_string_list[] = { + (uint16_t) LIT_MAGIC_STRING_INT8_ARRAY_UL, /**< Int8Array */ + (uint16_t) LIT_MAGIC_STRING_UINT8_ARRAY_UL, /**< Uint8Array */ + (uint16_t) LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL, /**< Uint8ClampedArray */ + (uint16_t) LIT_MAGIC_STRING_INT16_ARRAY_UL, /**< Int16Array */ + (uint16_t) LIT_MAGIC_STRING_UINT16_ARRAY_UL, /**< Uint16Array */ + (uint16_t) LIT_MAGIC_STRING_INT32_ARRAY_UL, /**< Int32Array */ + (uint16_t) LIT_MAGIC_STRING_UINT32_ARRAY_UL, /**< Uint32Array */ + (uint16_t) LIT_MAGIC_STRING_FLOAT32_ARRAY_UL, /**< Float32Array */ +#if JERRY_NUMBER_TYPE_FLOAT64 + (uint16_t) LIT_MAGIC_STRING_FLOAT64_ARRAY_UL, /**< Float64Array */ +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_BIGINT + (uint16_t) LIT_MAGIC_STRING_BIGINT64_ARRAY_UL, /**< BigInt64Array */ + (uint16_t) LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL, /**< BigUInt64Array */ +#endif /* JERRY_BUILTIN_BIGINT */ +}; + +/** + * Get the magic string id of a typedarray + * + * @return magic string + */ +lit_magic_string_id_t +ecma_get_typedarray_magic_string_id (ecma_typedarray_type_t typedarray_id) +{ + return (lit_magic_string_id_t) ecma_typedarray_magic_string_list[typedarray_id]; +} /* ecma_get_typedarray_magic_string_id */ + +/** + * Get typedarray's getter function callback + * + * @return ecma_typedarray_getter_fn_t: the getter function for the given builtin TypedArray id + */ +ecma_typedarray_getter_fn_t +ecma_get_typedarray_getter_fn (ecma_typedarray_type_t typedarray_id) /**< typedarray id */ +{ + return ecma_typedarray_getters[typedarray_id]; +} /* ecma_get_typedarray_getter_fn */ + +/** + * Get element from a TypedArray + * + * @return the value of the element + */ +ecma_value_t +ecma_get_typedarray_element (ecma_typedarray_info_t *info_p, /**< typedarray info */ + uint32_t index) /**< element index */ +{ + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info_p->array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p) || index >= info_p->length) + { + return ECMA_VALUE_UNDEFINED; + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + return ecma_typedarray_getters[info_p->id](buffer_p + (index << info_p->shift)); +} /* ecma_get_typedarray_element */ + +/** + * Get typedarray's setter function callback + * + * @return ecma_typedarray_setter_fn_t: the setter function for the given builtin TypedArray id + */ +ecma_typedarray_setter_fn_t +ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id) /**< typedarray id */ +{ + return ecma_typedarray_setters[typedarray_id]; +} /* ecma_get_typedarray_setter_fn */ + +/** + * set typedarray's element value + */ +ecma_value_t +ecma_set_typedarray_element (ecma_typedarray_info_t *info_p, /**< typedarray info */ + ecma_value_t value, /**< value to be set */ + uint32_t index) /**< element index */ +{ + ecma_value_t to_num; + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id)) + { + to_num = ecma_bigint_to_bigint (value, false); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + } + else + { + ecma_number_t result_num; + to_num = ecma_op_to_numeric (value, &result_num, ECMA_TO_NUMERIC_NO_OPTS); + + if (ECMA_IS_VALUE_ERROR (to_num)) + { + return to_num; + } + } + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info_p->array_buffer_p)) + { + ecma_free_value (to_num); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info_p->array_buffer_p) || index >= info_p->length) + { + ecma_free_value (to_num); + return ECMA_VALUE_FALSE; + } + + uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p); + + ecma_free_value (to_num); + + return ecma_typedarray_setters[info_p->id](buffer_p + (index << info_p->shift), value); +} /* ecma_set_typedarray_element */ + +/** + * Get the element shift size of a TypedArray type. + * + * @return uint8_t + */ +uint8_t +ecma_typedarray_helper_get_shift_size (ecma_typedarray_type_t typedarray_id) +{ + return ecma_typedarray_element_shift_sizes[typedarray_id]; +} /* ecma_typedarray_helper_get_shift_size */ + +/** + * Check if the builtin is a TypedArray type. + * + * @return bool: - true if based on the given id it is a TypedArray + * - false if based on the given id it is not a TypedArray + */ +bool +ecma_typedarray_helper_is_typedarray (ecma_builtin_id_t builtin_id) /**< the builtin id of a type **/ +{ + return ((builtin_id >= ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID) + && (builtin_id <= ECMA_LAST_TYPEDARRAY_BUILTIN_ROUTINE_ID)); +} /* ecma_typedarray_helper_is_typedarray */ + +/** + * Get the prototype ID of a TypedArray type. + * + * @return ecma_builtin_id_t + */ +ecma_builtin_id_t +ecma_typedarray_helper_get_prototype_id (ecma_typedarray_type_t typedarray_id) /**< the id of the typedarray **/ +{ + return (ecma_builtin_id_t) (ECMA_FIRST_TYPEDARRAY_BUILTIN_PROTOTYPE_ID + typedarray_id); +} /* ecma_typedarray_helper_get_prototype_id */ + +/** + * Get the constructor ID of a TypedArray type. + * + * @return ecma_builtin_id_t + */ +ecma_builtin_id_t +ecma_typedarray_helper_get_constructor_id (ecma_typedarray_type_t typedarray_id) /**< the id of the typedarray **/ +{ + return (ecma_builtin_id_t) (ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID + typedarray_id); +} /* ecma_typedarray_helper_get_constructor_id */ + +/** + * Get the built-in TypedArray type of the given object. + * + * @return ecma_typedarray_type_t + */ +ecma_typedarray_type_t +ecma_get_typedarray_id (ecma_object_t *obj_p) /**< typedarray object **/ +{ + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + return (ecma_typedarray_type_t) ext_object_p->u.cls.u1.typedarray_type; +} /* ecma_get_typedarray_id */ + +/** + * Get the built-in TypedArray type of the given object. + * + * @return ecma_typedarray_type_t + */ +ecma_typedarray_type_t +ecma_typedarray_helper_builtin_to_typedarray_id (ecma_builtin_id_t builtin_id) +{ + JERRY_ASSERT (ecma_typedarray_helper_is_typedarray (builtin_id)); + + return (ecma_typedarray_type_t) (builtin_id - ECMA_FIRST_TYPEDARRAY_BUILTIN_ROUTINE_ID); +} /* ecma_typedarray_helper_builtin_to_typedarray_id */ + +/** + * Create a TypedArray object by given array_length + * + * See also: ES2015 22.2.1.2.1 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_typedarray_create_object_with_length (uint32_t array_length, /**< length of the typedarray */ + ecma_object_t *src_buffer_p, /**< source buffer */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + uint32_t byte_length = UINT32_MAX; + + if (array_length <= (UINT32_MAX >> element_size_shift)) + { + byte_length = array_length << element_size_shift; + } + + if (byte_length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1) + { +#if JERRY_ERROR_MESSAGES + ecma_value_t array_length_value = ecma_make_number_value (array_length); + + ecma_value_t result = + ecma_raise_standard_error_with_format (JERRY_ERROR_RANGE, "Invalid typed array length: %", array_length_value); + ecma_free_value (array_length_value); + return result; +#else /* !JERRY_ERROR_MESSAGES */ + return ecma_raise_range_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + } + + ecma_object_t *new_arraybuffer_p = NULL; + if (src_buffer_p == NULL) + { + new_arraybuffer_p = ecma_arraybuffer_new_object (byte_length); + } + else + { + ecma_value_t ctor_proto = ecma_op_species_constructor (src_buffer_p, ECMA_BUILTIN_ID_ARRAYBUFFER); + + if (ECMA_IS_VALUE_ERROR (ctor_proto)) + { + return ctor_proto; + } + + ecma_object_t *ctor_proto_p = ecma_get_object_from_value (ctor_proto); + + ecma_object_t *prototype_p = + ecma_op_get_prototype_from_constructor (ctor_proto_p, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE); + + ecma_deref_object (ctor_proto_p); + + if (JERRY_UNLIKELY (prototype_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + new_arraybuffer_p = ecma_arraybuffer_new_object (byte_length); + + ECMA_SET_NON_NULL_POINTER (new_arraybuffer_p->u2.prototype_cp, prototype_p); + + ecma_deref_object (prototype_p); + + if (ecma_arraybuffer_is_detached (src_buffer_p)) + { + ecma_deref_object (new_arraybuffer_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + } + + ecma_object_t *object_p = ecma_create_object (proto_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_TYPEDARRAY; + ext_object_p->u.cls.u1.typedarray_type = (uint8_t) typedarray_id; + ext_object_p->u.cls.u2.typedarray_flags = 0; + ext_object_p->u.cls.u3.arraybuffer = ecma_make_object_value (new_arraybuffer_p); + + ecma_deref_object (new_arraybuffer_p); + + return ecma_make_object_value (object_p); +} /* ecma_typedarray_create_object_with_length */ + +/** + * Create a TypedArray object by given another TypedArray object + * + * See also: ES2015 22.2.1.3 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**< a typedarray object */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + uint32_t array_length = ecma_typedarray_get_length (typedarray_p); + ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (src_arraybuffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (src_arraybuffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (array_length, + src_arraybuffer_p, + proto_p, + element_size_shift, + typedarray_id); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_object_t *dst_arraybuffer_p = ecma_typedarray_get_arraybuffer (new_typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (dst_arraybuffer_p)) + { + ecma_deref_object (new_typedarray_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (dst_arraybuffer_p)) + { + ecma_deref_object (new_typedarray_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + lit_utf8_byte_t *src_buf_p = ecma_arraybuffer_get_buffer (src_arraybuffer_p); + lit_utf8_byte_t *dst_buf_p = ecma_arraybuffer_get_buffer (dst_arraybuffer_p); + + src_buf_p += ecma_typedarray_get_offset (typedarray_p); + + ecma_typedarray_type_t src_id = ecma_get_typedarray_id (typedarray_p); + + if (src_id == typedarray_id) + { + memcpy (dst_buf_p, src_buf_p, array_length << element_size_shift); + } + else + { +#if JERRY_BUILTIN_BIGINT + if ((ECMA_TYPEDARRAY_IS_BIGINT_TYPE (src_id) ^ ECMA_TYPEDARRAY_IS_BIGINT_TYPE (typedarray_id)) == 1) + { + ecma_deref_object (new_typedarray_p); + return ecma_raise_type_error (ECMA_ERR_INCOMPATIBLE_TYPEDARRAY_TYPES); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + uint32_t src_element_size = 1u << ecma_typedarray_get_element_size_shift (typedarray_p); + uint32_t dst_element_size = 1u << element_size_shift; + ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_id); + ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (typedarray_id); + + for (uint32_t i = 0; i < array_length; i++) + { + /* Convert values from source to destination format. */ + ecma_value_t tmp = src_typedarray_getter_cb (src_buf_p); + ecma_value_t set_element = target_typedarray_setter_cb (dst_buf_p, tmp); + + ecma_free_value (tmp); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + ecma_deref_object (new_typedarray_p); + return set_element; + } + + src_buf_p += src_element_size; + dst_buf_p += dst_element_size; + } + } + + return new_typedarray; +} /* ecma_typedarray_create_object_with_typedarray */ + +/** + * Helper method for ecma_op_typedarray_from + * + * @return ECMA_VALUE_TRUE - if setting the given value to the new typedarray was successful + * ECMA_VALUE_ERROR - otherwise + */ +static ecma_value_t +ecma_op_typedarray_from_helper (ecma_value_t this_val, /**< this_arg for the above from function */ + ecma_value_t current_value, /**< given value to set */ + uint32_t index, /**< currrent index */ + ecma_object_t *func_object_p, /**< map function object */ + uint8_t *buffer_p, /**< target buffer */ + ecma_typedarray_setter_fn_t setter_cb) /**< setter callback function */ +{ + ecma_value_t mapped_value = current_value; + + if (func_object_p != NULL) + { + /* 17.d 17.f */ + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t call_args[] = { current_value, current_index }; + + ecma_value_t cb_value = ecma_op_function_call (func_object_p, this_val, call_args, 2); + + ecma_free_value (current_value); + ecma_free_value (current_index); + + if (ECMA_IS_VALUE_ERROR (cb_value)) + { + return cb_value; + } + + mapped_value = cb_value; + } + + ecma_value_t set_element = setter_cb (buffer_p, mapped_value); + ecma_free_value (mapped_value); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_typedarray_from_helper */ + +/** + * Create a TypedArray object by transforming from an array-like object or iterable object + * + * See also: ES11 22.2.4.4 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_typedarray_create_object_with_object (ecma_value_t items_val, /**< the source array-like object */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + /* 5 */ + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (items_val, LIT_GLOBAL_SYMBOL_ITERATOR); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + ecma_object_t *new_typedarray_p; + ecma_typedarray_info_t info; + ecma_value_t *next_value_p; + + uint8_t *buffer_p; + ecma_typedarray_setter_fn_t setter_cb; + uint8_t *limit_p; + + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + return using_iterator; + } + + /* 6 */ + if (!ecma_is_value_undefined (using_iterator)) + { + /* 6.a */ + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (items_val, using_iterator, &next_method); + ecma_free_value (using_iterator); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + return iterator; + } + + ecma_collection_t *values_p = ecma_new_collection (); + + while (true) + { + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next)) + { + ret_value = next; + break; + } + + if (next == ECMA_VALUE_FALSE) + { + break; + } + + ecma_value_t next_value = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + ret_value = next_value; + break; + } + + ecma_collection_push_back (values_p, next_value); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_collection_free (values_p); + return ret_value; + } + + /* 8.c */ + ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (values_p->item_count, + NULL, + proto_p, + element_size_shift, + typedarray_id); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_collection_free (values_p); + return new_typedarray; + } + + new_typedarray_p = ecma_get_object_from_value (new_typedarray); + info = ecma_typedarray_get_info (new_typedarray_p); + next_value_p = values_p->buffer_p; + + ret_value = ECMA_VALUE_ERROR; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_collection; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_collection; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + setter_cb = ecma_get_typedarray_setter_fn (info.id); + limit_p = buffer_p + (values_p->item_count << info.shift); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 8.e */ + while (buffer_p < limit_p) + { + ecma_value_t value = *next_value_p++; + ecma_value_t set_value = setter_cb (buffer_p, value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_collection: + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_value_t *last_value_p = values_p->buffer_p + values_p->item_count; + + while (next_value_p < last_value_p) + { + ecma_free_value (*next_value_p++); + } + + ecma_deref_object (new_typedarray_p); + } + + ecma_collection_destroy (values_p); + return ret_value; + } + + /* 8 */ + ecma_value_t arraylike_object_val = ecma_op_to_object (items_val); + + if (ECMA_IS_VALUE_ERROR (arraylike_object_val)) + { + return arraylike_object_val; + } + + ecma_object_t *arraylike_object_p = ecma_get_object_from_value (arraylike_object_val); + + /* 9 */ + ecma_length_t length_index; + ecma_value_t len_value = ecma_op_object_get_length (arraylike_object_p, &length_index); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (arraylike_object_p); + return len_value; + } + + if (length_index >= UINT32_MAX) + { + ecma_deref_object (arraylike_object_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_TYPEDARRAY_LENGTH); + } + + uint32_t len = (uint32_t) length_index; + + /* 10 */ + ecma_value_t new_typedarray = + ecma_typedarray_create_object_with_length (len, NULL, proto_p, element_size_shift, typedarray_id); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_deref_object (arraylike_object_p); + return new_typedarray; + } + + new_typedarray_p = ecma_get_object_from_value (new_typedarray); + info = ecma_typedarray_get_info (new_typedarray_p); + ret_value = ECMA_VALUE_ERROR; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_object; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_object; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + setter_cb = ecma_get_typedarray_setter_fn (info.id); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 12 */ + for (uint32_t index = 0; index < len; index++) + { + ecma_value_t value = ecma_op_object_find_by_index (arraylike_object_p, index); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ret_value = value; + break; + } + + if (!ecma_is_value_found (value)) + { + value = ECMA_VALUE_UNDEFINED; + } + + ecma_value_t set_value = setter_cb (buffer_p, value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_object: + ecma_deref_object (arraylike_object_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_typedarray_p); + } + + return ret_value; +} /* ecma_typedarray_create_object_with_object */ + +/** + * Create a TypedArray object by transforming from an array-like object or iterable object + * + * See also: ES11 22.2.2.1 + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_typedarray_from (ecma_value_t this_val, /**< this value */ + ecma_value_t source_val, /**< source value */ + ecma_value_t map_fn_val, /**< mapped function value */ + ecma_value_t this_arg) /**< this argument */ +{ + JERRY_UNUSED (this_arg); + /* 3 */ + JERRY_ASSERT (ecma_op_is_callable (map_fn_val) || ecma_is_value_undefined (map_fn_val)); + + /* 4 */ + ecma_object_t *func_object_p = NULL; + + if (!ecma_is_value_undefined (map_fn_val)) + { + func_object_p = ecma_get_object_from_value (map_fn_val); + } + + /* 5 */ + ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (source_val, LIT_GLOBAL_SYMBOL_ITERATOR); + + if (ECMA_IS_VALUE_ERROR (using_iterator)) + { + return using_iterator; + } + + /* 6 */ + if (!ecma_is_value_undefined (using_iterator)) + { + /* 6.a */ + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (source_val, using_iterator, &next_method); + ecma_free_value (using_iterator); + + /* 6.b */ + if (ECMA_IS_VALUE_ERROR (iterator)) + { + return iterator; + } + + /* 6.c */ + ecma_collection_t *values_p = ecma_new_collection (); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 6.e */ + while (true) + { + ecma_value_t next = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next)) + { + ret_value = next; + break; + } + + if (next == ECMA_VALUE_FALSE) + { + break; + } + + ecma_value_t next_value = ecma_op_iterator_value (next); + ecma_free_value (next); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + ret_value = next_value; + break; + } + + ecma_collection_push_back (values_p, next_value); + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_collection_free (values_p); + return ret_value; + } + + /* 6.c */ + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (this_val); + ecma_value_t len_val = ecma_make_uint32_value (values_p->item_count); + ecma_value_t new_typedarray = ecma_typedarray_create (constructor_obj_p, &len_val, 1); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_collection_free (values_p); + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p); + ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id); + ecma_value_t *next_value_p = values_p->buffer_p; + uint8_t *buffer_p; + + ret_value = ECMA_VALUE_ERROR; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_collection; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_collection; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 6.e */ + for (uint32_t index = 0; index < values_p->item_count; index++) + { + ecma_value_t set_value = + ecma_op_typedarray_from_helper (this_arg, *next_value_p++, index, func_object_p, buffer_p, setter_cb); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_collection: + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_value_t *last_value_p = values_p->buffer_p + values_p->item_count; + + while (next_value_p < last_value_p) + { + ecma_free_value (*next_value_p++); + } + + ecma_deref_object (new_typedarray_p); + } + + ecma_collection_destroy (values_p); + return ret_value; + } + + /* 8 */ + ecma_value_t arraylike_object_val = ecma_op_to_object (source_val); + + if (ECMA_IS_VALUE_ERROR (arraylike_object_val)) + { + return arraylike_object_val; + } + + ecma_object_t *arraylike_object_p = ecma_get_object_from_value (arraylike_object_val); + + /* 9 */ + ecma_length_t length_index; + ecma_value_t len_value = ecma_op_object_get_length (arraylike_object_p, &length_index); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (arraylike_object_p); + return len_value; + } + + if (length_index >= UINT32_MAX) + { + ecma_deref_object (arraylike_object_p); + return ecma_raise_range_error (ECMA_ERR_INVALID_TYPEDARRAY_LENGTH); + } + + uint32_t len = (uint32_t) length_index; + + /* 10 */ + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (this_val); + ecma_value_t len_val = ecma_make_uint32_value (len); + ecma_value_t new_typedarray = ecma_typedarray_create (constructor_obj_p, &len_val, 1); + ecma_free_value (len_val); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + ecma_deref_object (arraylike_object_p); + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + uint8_t *buffer_p; + + ecma_typedarray_setter_fn_t setter_cb; + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + goto free_object; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + goto free_object; + } + + buffer_p = ecma_typedarray_get_buffer (&info); + setter_cb = ecma_get_typedarray_setter_fn (info.id); + ret_value = ecma_make_object_value (new_typedarray_p); + + /* 12 */ + for (uint32_t index = 0; index < len; index++) + { + ecma_value_t value = ecma_op_object_find_by_index (arraylike_object_p, index); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ret_value = value; + break; + } + + if (!ecma_is_value_found (value)) + { + value = ECMA_VALUE_UNDEFINED; + } + + ecma_value_t set_value = + ecma_op_typedarray_from_helper (this_arg, value, index, func_object_p, buffer_p, setter_cb); + + if (ECMA_IS_VALUE_ERROR (set_value)) + { + ret_value = set_value; + break; + } + + buffer_p += info.element_size; + } + +free_object: + ecma_deref_object (arraylike_object_p); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_typedarray_p); + } + + return ret_value; +} /* ecma_op_typedarray_from */ + +/** + * Get the arraybuffer of the typedarray object + * + * @return the pointer to the internal arraybuffer + */ +ecma_object_t * +ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; + + return ecma_get_object_from_value (ext_object_p->u.cls.u3.arraybuffer); +} /* ecma_typedarray_get_arraybuffer */ + +/** + * Get the element size shift in the typedarray object + * + * @return the size shift of the element, size is 1 << shift + */ +uint8_t +ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + return ecma_typedarray_helper_get_shift_size (ecma_get_typedarray_id (typedarray_p)); +} /* ecma_typedarray_get_element_size_shift */ + +/** + * Get the array length of the typedarray object + * + * @return the array length + */ +uint32_t +ecma_typedarray_get_length (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; + + if (!(ext_object_p->u.cls.u2.typedarray_flags & ECMA_TYPEDARRAY_IS_EXTENDED)) + { + ecma_object_t *arraybuffer_p = ecma_get_object_from_value (ext_object_p->u.cls.u3.arraybuffer); + ecma_extended_object_t *arraybuffer_object_p = (ecma_extended_object_t *) arraybuffer_p; + uint32_t buffer_length = arraybuffer_object_p->u.cls.u3.length; + uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p); + + return buffer_length >> shift; + } + + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return 0; + } + + ecma_extended_typedarray_object_t *info_p = (ecma_extended_typedarray_object_t *) ext_object_p; + + return info_p->array_length; +} /* ecma_typedarray_get_length */ + +/** + * Get the offset of the internal arraybuffer + * + * @return the offset + */ +uint32_t +ecma_typedarray_get_offset (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; + + if (!(ext_object_p->u.cls.u2.typedarray_flags & ECMA_TYPEDARRAY_IS_EXTENDED)) + { + return 0; + } + + ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return 0; + } + + ecma_extended_typedarray_object_t *info_p = (ecma_extended_typedarray_object_t *) ext_object_p; + + return info_p->byte_offset; +} /* ecma_typedarray_get_offset */ + +/** + * Utility function: return the pointer of the data buffer referenced by the typedarray info + * + * @return pointer to the data buffer if successfull, + * NULL otherwise + */ +uint8_t * +ecma_typedarray_get_buffer (ecma_typedarray_info_t *info_p) /**< typedarray info */ +{ + return ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset; +} /* ecma_typedarray_get_buffer */ + +/** + * Create a new typedarray object. + * + * The struct of the typedarray object + * ecma_object_t + * extend_part + * typedarray_info + * + * @return ecma value of the new typedarray object + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg list passed to typedarray construct */ + uint32_t arguments_list_len, /**< the length of the arguments_list_p */ + ecma_object_t *proto_p, /**< prototype object */ + uint8_t element_size_shift, /**< the size shift of the element length */ + ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (arguments_list_len == 0) + { + /* 22.2.1.1 */ + return ecma_typedarray_create_object_with_length (0, NULL, proto_p, element_size_shift, typedarray_id); + } + + if (!ecma_is_value_object (arguments_list_p[0])) + { + ecma_number_t num = 0; + + if (!ecma_is_value_undefined (arguments_list_p[0]) + && ECMA_IS_VALUE_ERROR (ecma_op_to_index (arguments_list_p[0], &num))) + { + return ECMA_VALUE_ERROR; + } + + JERRY_ASSERT (num >= 0 && num <= ECMA_NUMBER_MAX_SAFE_INTEGER); + + if (num > UINT32_MAX) + { +#if JERRY_ERROR_MESSAGES + return ecma_raise_standard_error_with_format (JERRY_ERROR_RANGE, + "Invalid typed array length: %", + arguments_list_p[0]); +#else /* !JERRY_ERROR_MESSAGES */ + return ecma_raise_range_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + } + + return ecma_typedarray_create_object_with_length ((uint32_t) num, NULL, proto_p, element_size_shift, typedarray_id); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list_p[0]); + + if (ecma_object_is_typedarray (obj_p)) + { + /* 22.2.1.3 */ + ecma_object_t *typedarray_p = obj_p; + return ecma_typedarray_create_object_with_typedarray (typedarray_p, proto_p, element_size_shift, typedarray_id); + } + + if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER) && !ecma_object_is_shared_arraybuffer (obj_p)) + { + /* 22.2.1.4 */ + return ecma_typedarray_create_object_with_object (arguments_list_p[0], proto_p, element_size_shift, typedarray_id); + } + + /* 22.2.1.5 */ + ecma_object_t *arraybuffer_p = obj_p; + ecma_value_t byte_offset_value = ((arguments_list_len > 1) ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED); + + ecma_value_t length_value = ((arguments_list_len > 2) ? arguments_list_p[2] : ECMA_VALUE_UNDEFINED); + + ecma_number_t offset; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (byte_offset_value, &offset))) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_number_is_negative (offset) || fmod (offset, (1 << element_size_shift)) != 0) + { + /* ES2015 22.2.1.5: 9 - 10. */ + if (ecma_number_is_zero (offset)) + { + offset = 0; + } + else + { + return ecma_raise_range_error (ECMA_ERR_INVALID_OFFSET); + } + } + + ecma_number_t new_length = 0; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (length_value, &new_length))) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (arraybuffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if (offset > UINT32_MAX) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + + uint32_t byte_offset = (uint32_t) offset; + + uint32_t buf_byte_length = ecma_arraybuffer_get_length (arraybuffer_p); + uint32_t new_byte_length = 0; + + if (ecma_is_value_undefined (length_value)) + { + if ((buf_byte_length % (uint32_t) (1 << element_size_shift) != 0) || (buf_byte_length < byte_offset)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + + new_byte_length = (uint32_t) (buf_byte_length - byte_offset); + } + else + { + if (new_length > (UINT32_MAX >> element_size_shift)) + { + return ecma_raise_range_error (ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED); + } + + new_byte_length = (uint32_t) new_length << element_size_shift; + + if (byte_offset > buf_byte_length || new_byte_length > (buf_byte_length - byte_offset)) + { + return ecma_raise_range_error (ECMA_ERR_INVALID_LENGTH); + } + } + + bool needs_ext_typedarray_obj = (byte_offset != 0 || new_byte_length != buf_byte_length); + + size_t object_size = + (needs_ext_typedarray_obj ? sizeof (ecma_extended_typedarray_object_t) : sizeof (ecma_extended_object_t)); + + ecma_object_t *object_p = ecma_create_object (proto_p, object_size, ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_TYPEDARRAY; + ext_object_p->u.cls.u1.typedarray_type = (uint8_t) typedarray_id; + ext_object_p->u.cls.u2.typedarray_flags = 0; + ext_object_p->u.cls.u3.arraybuffer = ecma_make_object_value (arraybuffer_p); + + if (needs_ext_typedarray_obj) + { + ext_object_p->u.cls.u2.typedarray_flags |= ECMA_TYPEDARRAY_IS_EXTENDED; + + ecma_extended_typedarray_object_t *typedarray_info_p = (ecma_extended_typedarray_object_t *) object_p; + typedarray_info_p->array_length = new_byte_length >> element_size_shift; + typedarray_info_p->byte_offset = byte_offset; + } + + return ecma_make_object_value (object_p); +} /* ecma_op_create_typedarray */ + +/** + * Helper function for typedArray.prototype object's {'keys', 'values', 'entries', '@@iterator'} + * routines common parts. + * + * See also: + * ECMA-262 v6, 22.2.3.15 + * ECMA-262 v6, 22.2.3.29 + * ECMA-262 v6, 22.2.3.6 + * ECMA-262 v6, 22.1.3.30 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +ecma_value_t +ecma_typedarray_iterators_helper (ecma_value_t this_arg, /**< this argument */ + ecma_iterator_kind_t kind) /**< iterator kind */ +{ + JERRY_ASSERT (ecma_is_typedarray (this_arg)); + + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE); + + return ecma_op_create_iterator_object (this_arg, prototype_obj_p, ECMA_OBJECT_CLASS_ARRAY_ITERATOR, kind); +} /* ecma_typedarray_iterators_helper */ + +/** + * Check if the object is typedarray + * + * @return true - if object is a TypedArray object + * false - otherwise + */ +bool +ecma_object_is_typedarray (ecma_object_t *obj_p) /**< the target object need to be checked */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + return ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_TYPEDARRAY); +} /* ecma_object_is_typedarray */ + +/** + * Check if the value is typedarray + * + * @return true - if value is a TypedArray object + * false - otherwise + */ +bool +ecma_is_typedarray (ecma_value_t value) /**< the target need to be checked */ +{ + if (!ecma_is_value_object (value)) + { + return false; + } + + return ecma_object_is_typedarray (ecma_get_object_from_value (value)); +} /* ecma_is_typedarray */ + +/** + * Checks whether the property name is a valid element index + * + * @return true, if valid + * false, otherwise + */ +bool +ecma_typedarray_is_element_index (ecma_string_t *property_name_p) /**< property name */ +{ + ecma_number_t num = ecma_string_to_number (property_name_p); + + if (num == 0) + { + return true; + } + + ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num); + bool is_same = ecma_compare_ecma_strings (property_name_p, num_to_str); + ecma_deref_ecma_string (num_to_str); + return is_same; +} /* ecma_typedarray_is_element_index */ + +/** + * List names of a TypedArray object's integer indexed properties + */ +void +ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedArray object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + { + return; + } + + uint32_t array_length = ecma_typedarray_get_length (obj_p); + + for (uint32_t i = 0; i < array_length; i++) + { + ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); + ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); + } + + prop_counter_p->array_index_named_props += array_length; +} /* ecma_op_typedarray_list_lazy_property_names */ + +/** + * [[DefineOwnProperty]] operation for TypedArray objects + * + * See also: ES2015 9.4.5.3 + * + * @return ECMA_VALUE_TRUE - if the property is successfully defined + * ECMA_VALUE_FALSE - if is JERRY_PROP_SHOULD_THROW is not set + * raised TypeError - otherwise + */ +ecma_value_t +ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, /**< TypedArray object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX && !ecma_typedarray_is_element_index (property_name_p)) + { + return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); + } + + if ((property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + || ((property_desc_p->flags & (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)) + == (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)) + || ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)) + || ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE))) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p); + + if (index >= info.length || ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + return ECMA_VALUE_FALSE; + } + + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_value_t set_element = ecma_set_typedarray_element (&info, property_desc_p->value, index); + + if (ECMA_IS_VALUE_ERROR (set_element)) + { + return set_element; + } + } + + return ECMA_VALUE_TRUE; +} /* ecma_op_typedarray_define_own_property */ + +/** + * Specify the creation of a new TypedArray + * object using a constructor function. + * + * See also: ES11 22.2.4.6 + * + * Used by: + * - ecma_typedarray_species_create + * + * @return ecma_value_t function object from created from constructor_p argument + */ + +ecma_value_t +ecma_typedarray_create (ecma_object_t *constructor_p, /**< constructor function */ + ecma_value_t *arguments_list_p, /**< argument list */ + uint32_t arguments_list_len) /**< length of argument list */ +{ + ecma_value_t ret_val = + ecma_op_function_construct (constructor_p, constructor_p, arguments_list_p, arguments_list_len); + if (ECMA_IS_VALUE_ERROR (ret_val)) + { + return ret_val; + } + + if (!ecma_is_typedarray (ret_val)) + { + ecma_free_value (ret_val); + return ecma_raise_type_error (ECMA_ERR_CONSTRUCTED_OBJECT_IS_NOT_TYPEDARRAY); + } + + ecma_object_t *typedarray_p = ecma_get_object_from_value (ret_val); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + if (ECMA_ARRAYBUFFER_LAZY_ALLOC (info.array_buffer_p)) + { + ecma_deref_object (typedarray_p); + return ECMA_VALUE_ERROR; + } + + if (ecma_arraybuffer_is_detached (info.array_buffer_p)) + { + ecma_deref_object (typedarray_p); + return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED); + } + + if ((arguments_list_len == 1) && (ecma_is_value_number (arguments_list_p[0]))) + { + ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]); + + if (info.length < num) + { + ecma_free_value (ret_val); + return ecma_raise_type_error (ECMA_ERR_TYPEDARRAY_SMALLER_THAN_FILTER_CALL_RESULT); + } + } + return ret_val; +} /* ecma_typedarray_create */ + +/* Specify the creation of a new TypedArray object + * using a constructor function that is derived from this_arg. + * + * See also: ES11 22.2.4.7 + * + * @return ecma value of the new typedarray object, constructed by default or species constructor + */ +ecma_value_t +ecma_typedarray_species_create (ecma_value_t this_arg, /**< this argument */ + ecma_value_t *arguments_list_p, /**< the arg list passed to typedarray construct */ + uint32_t arguments_list_len) /**< length of the the arg list */ +{ + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + + JERRY_ASSERT (ecma_is_typedarray (this_arg)); + + ecma_builtin_id_t default_constructor = ecma_typedarray_helper_get_constructor_id (info.id); + + ecma_value_t constructor = ecma_op_species_constructor (typedarray_p, default_constructor); + + if (ECMA_IS_VALUE_ERROR (constructor)) + { + return constructor; + } + + ecma_object_t *constructor_proto_p = ecma_get_object_from_value (constructor); + + ecma_value_t result = ecma_typedarray_create (constructor_proto_p, arguments_list_p, arguments_list_len); + ecma_deref_object (constructor_proto_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + +#if JERRY_BUILTIN_BIGINT + ecma_object_t *result_p = ecma_get_object_from_value (result); + ecma_typedarray_info_t result_info = ecma_typedarray_get_info (result_p); + /* + * Check result_info.id to to be either bigint type if info.id is one + * or be neither of them is info.id is none of them as well. + */ + if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info.id) ^ ECMA_TYPEDARRAY_IS_BIGINT_TYPE (result_info.id)) + { + ecma_free_value (result); + return ecma_raise_type_error (ECMA_ERR_CONTENTTYPE_RETURNED_TYPEDARRAY_NOT_MATCH_SOURCE); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + return result; +} /* ecma_typedarray_species_create */ + +/** + * Create a typedarray object based on the "type" and arraylength + * The "type" is same with arg1 + * + * @return ecma_value_t + */ +ecma_value_t +ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id, /** TypedArray id */ + uint32_t array_length) /**< length of the typedarray */ +{ + // TODO: assert validate typedarray_id + ecma_object_t *proto_p = ecma_builtin_get (ecma_typedarray_helper_get_prototype_id (typedarray_id)); + uint8_t element_size_shift = ecma_typedarray_helper_get_shift_size (typedarray_id); + + ecma_value_t new_obj = + ecma_typedarray_create_object_with_length (array_length, NULL, proto_p, element_size_shift, typedarray_id); + + return new_obj; +} /* ecma_op_create_typedarray_with_type_and_length */ + +/** + * Method for getting the additional typedArray informations. + */ +ecma_typedarray_info_t +ecma_typedarray_get_info (ecma_object_t *typedarray_p) +{ + ecma_typedarray_info_t info; + + info.id = ecma_get_typedarray_id (typedarray_p); + info.length = ecma_typedarray_get_length (typedarray_p); + info.shift = ecma_typedarray_get_element_size_shift (typedarray_p); + info.element_size = (uint8_t) (1 << info.shift); + info.offset = ecma_typedarray_get_offset (typedarray_p); + info.array_buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + + return info; +} /* ecma_typedarray_get_info */ + +/** + * @} + * @} + */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.h b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.h new file mode 100644 index 00000000..ab004265 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/ecma-typedarray-object.h @@ -0,0 +1,89 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_TYPEDARRAY_OBJECT_H +#define ECMA_TYPEDARRAY_OBJECT_H + +#include "ecma-builtins.h" +#include "ecma-globals.h" + +#if JERRY_BUILTIN_TYPEDARRAY + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmatypedarrayobject ECMA TypedArray object related routines + * @{ + */ + +uint8_t ecma_typedarray_helper_get_shift_size (ecma_typedarray_type_t typedarray_id); +lit_magic_string_id_t ecma_get_typedarray_magic_string_id (ecma_typedarray_type_t typedarray_id); +ecma_typedarray_getter_fn_t ecma_get_typedarray_getter_fn (ecma_typedarray_type_t typedarray_id); +ecma_typedarray_setter_fn_t ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id); +ecma_value_t ecma_get_typedarray_element (ecma_typedarray_info_t *info_p, uint32_t index); +ecma_value_t ecma_set_typedarray_element (ecma_typedarray_info_t *info_p, ecma_value_t value, uint32_t index); +bool ecma_typedarray_helper_is_typedarray (ecma_builtin_id_t builtin_id); +ecma_typedarray_type_t ecma_get_typedarray_id (ecma_object_t *obj_p); +ecma_builtin_id_t ecma_typedarray_helper_get_prototype_id (ecma_typedarray_type_t typedarray_id); +ecma_builtin_id_t ecma_typedarray_helper_get_constructor_id (ecma_typedarray_type_t typedarray_id); +ecma_typedarray_type_t ecma_typedarray_helper_builtin_to_typedarray_id (ecma_builtin_id_t builtin_id); + +ecma_value_t +ecma_op_typedarray_from (ecma_value_t this_val, ecma_value_t source_val, ecma_value_t mapfn_val, ecma_value_t this_arg); +uint32_t ecma_typedarray_get_length (ecma_object_t *typedarray_p); +uint32_t ecma_typedarray_get_offset (ecma_object_t *typedarray_p); +uint8_t *ecma_typedarray_get_buffer (ecma_typedarray_info_t *info_p); +uint8_t ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p); +ecma_object_t *ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p); +ecma_value_t ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len, + ecma_object_t *proto_p, + uint8_t element_size_shift, + ecma_typedarray_type_t typedarray_id); +ecma_value_t ecma_typedarray_iterators_helper (ecma_value_t this_arg, ecma_iterator_kind_t kind); + +bool ecma_object_is_typedarray (ecma_object_t *obj_p); +bool ecma_is_typedarray (ecma_value_t target); +bool ecma_typedarray_is_element_index (ecma_string_t *property_name_p); +void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +ecma_value_t ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id, + uint32_t array_length); +ecma_typedarray_info_t ecma_typedarray_get_info (ecma_object_t *typedarray_p); +ecma_value_t ecma_typedarray_create_object_with_length (uint32_t array_length, + ecma_object_t *src_arraybuffer_p, + ecma_object_t *proto_p, + uint8_t element_size_shift, + ecma_typedarray_type_t typedarray_id); +ecma_value_t ecma_typedarray_create_object_with_object (ecma_value_t items_val, + ecma_object_t *proto_p, + uint8_t element_size_shift, + ecma_typedarray_type_t typedarray_id); +ecma_value_t +ecma_typedarray_create (ecma_object_t *constructor_p, ecma_value_t *arguments_list_p, uint32_t arguments_list_len); +ecma_value_t ecma_typedarray_species_create (ecma_value_t this_arg, ecma_value_t *length, uint32_t arguments_list_len); + +/** + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#endif /* !ECMA_TYPEDARRAY_OBJECT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/meson.build b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/meson.build new file mode 100644 index 00000000..aa9fe30d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/ecma/operations/meson.build @@ -0,0 +1,68 @@ +source_file = [ + 'ecma-arguments-object.h', + 'ecma-array-object.h', + 'ecma-arraybuffer-object.h', + 'ecma-async-generator-object.h', + 'ecma-atomics-object.h', + 'ecma-big-uint.h', + 'ecma-bigint-object.h', + 'ecma-bigint.h', + 'ecma-boolean-object.h', + 'ecma-comparison.h', + 'ecma-container-object.h', + 'ecma-conversion.h', + 'ecma-dataview-object.h', + 'ecma-eval.h', + 'ecma-exceptions.h', + 'ecma-function-object.h', + 'ecma-iterator-object.h', + 'ecma-jobqueue.h', + 'ecma-lex-env.h', + 'ecma-number-object.h', + 'ecma-objects-general.h', + 'ecma-objects.h', + 'ecma-promise-object.h', + 'ecma-proxy-object.h', + 'ecma-reference.h', + 'ecma-regexp-object.h', + 'ecma-shared-arraybuffer-object.h', + 'ecma-string-object.h', + 'ecma-symbol-object.h', + 'ecma-typedarray-object.h', + 'ecma-arguments-object.cpp', + 'ecma-array-object.cpp', + 'ecma-arraybuffer-object.cpp', + 'ecma-async-generator-object.cpp', + 'ecma-atomics-object.cpp', + 'ecma-big-uint.cpp', + 'ecma-bigint-object.cpp', + 'ecma-bigint.cpp', + 'ecma-boolean-object.cpp', + 'ecma-comparison.cpp', + 'ecma-container-object.cpp', + 'ecma-conversion.cpp', + 'ecma-dataview-object.cpp', + 'ecma-eval.cpp', + 'ecma-exceptions.cpp', + 'ecma-function-object.cpp', + 'ecma-get-put-value.cpp', + 'ecma-iterator-object.cpp', + 'ecma-jobqueue.cpp', + 'ecma-lex-env.cpp', + 'ecma-number-object.cpp', + 'ecma-objects-general.cpp', + 'ecma-objects.cpp', + 'ecma-promise-object.cpp', + 'ecma-proxy-object.cpp', + 'ecma-reference.cpp', + 'ecma-regexp-object.cpp', + 'ecma-shared-arraybuffer-object.cpp', + 'ecma-string-object.cpp', + 'ecma-symbol-object.cpp', + 'ecma-typedarray-object.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerry-config.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerry-config.h new file mode 100644 index 00000000..ff48a6c0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerry-config.h @@ -0,0 +1,632 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_CONFIG_H +#define JERRYSCRIPT_CONFIG_H + +// @JERRY_BUILD_CFG@ + +/** + * Built-in configurations + * + * Allowed values for built-in defines: + * 0: Disable the given built-in. + * 1: Enable the given built-in. + */ +/* + * By default all built-ins are enabled if they are not defined. + */ +#ifndef JERRY_BUILTINS +#define JERRY_BUILTINS 1 +#endif /* !defined (JERRY_BUILTINS) */ + +#ifndef JERRY_BUILTIN_ANNEXB +#define JERRY_BUILTIN_ANNEXB JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_ANNEXB) */ + +#ifndef JERRY_BUILTIN_ARRAY +#define JERRY_BUILTIN_ARRAY JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_ARRAY) */ + +#ifndef JERRY_BUILTIN_BOOLEAN +#define JERRY_BUILTIN_BOOLEAN JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_BOOLEAN) */ + +#ifndef JERRY_BUILTIN_DATE +#define JERRY_BUILTIN_DATE JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_DATE) */ + +#ifndef JERRY_BUILTIN_ERRORS +#define JERRY_BUILTIN_ERRORS JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_ERRORS) */ + +#ifndef JERRY_BUILTIN_MATH +#define JERRY_BUILTIN_MATH JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_MATH) */ + +#ifndef JERRY_BUILTIN_NUMBER +#define JERRY_BUILTIN_NUMBER JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_NUMBER) */ + +#ifndef JERRY_BUILTIN_REGEXP +#define JERRY_BUILTIN_REGEXP JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_REGEXP) */ + +#ifndef JERRY_BUILTIN_STRING +#define JERRY_BUILTIN_STRING JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_STRING) */ + +#ifndef JERRY_BUILTIN_BIGINT +#define JERRY_BUILTIN_BIGINT JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_BIGINT) */ + +#ifndef JERRY_BUILTIN_CONTAINER +#define JERRY_BUILTIN_CONTAINER JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_CONTAINER) */ + +#ifndef JERRY_BUILTIN_DATAVIEW +#define JERRY_BUILTIN_DATAVIEW JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_DATAVIEW) */ + +#ifndef JERRY_BUILTIN_GLOBAL_THIS +#define JERRY_BUILTIN_GLOBAL_THIS JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_GLOBAL_THIS) */ + +#ifndef JERRY_BUILTIN_REALMS +#define JERRY_BUILTIN_REALMS JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_REALMS) */ + +#ifndef JERRY_BUILTIN_TYPEDARRAY +#define JERRY_BUILTIN_TYPEDARRAY JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_TYPEDARRAY) */ + +#ifndef JERRY_BUILTIN_SHAREDARRAYBUFFER +#define JERRY_BUILTIN_SHAREDARRAYBUFFER JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_SHAREDARRAYBUFFER) */ + +#ifndef JERRY_BUILTIN_WEAKREF +#define JERRY_BUILTIN_WEAKREF JERRY_BUILTINS +#endif /* !defined (JERRY_BUILTIN_WEAKREF) */ + +/** + * Engine internal and misc configurations. + */ + +/** + * Specifies the compressed pointer representation + * + * Allowed values: + * 0: use 16 bit representation + * 1: use 32 bit representation + * + * Default value: 0 + * For more details see: jmem/jmem.h + */ +#ifndef JERRY_CPOINTER_32_BIT +#define JERRY_CPOINTER_32_BIT 0 +#endif /* !defined (JERRY_CPOINTER_32_BIT) */ + +/** + * Enable/Disable built-in error messages for error objects. + * + * Allowed values: + * 0: Disable error messages. + * 1: Enable error message. + * + * Default value: 0 + */ +#ifndef JERRY_ERROR_MESSAGES +#define JERRY_ERROR_MESSAGES 0 +#endif /* !defined (JERRY_ERROR_MESSAGES) */ + +/** + * Enable/Disable external context. + * + * Allowed values: + * 0: Disable external context. + * 1: Enable external context support. + * + * Default value: 0 + */ +#ifndef JERRY_EXTERNAL_CONTEXT +#define JERRY_EXTERNAL_CONTEXT 0 +#endif /* !defined (JERRY_EXTERNAL_CONTEXT) */ + +/** + * Maximum size of heap in kilobytes + * + * Default value: 512 KiB + */ +#ifndef JERRY_GLOBAL_HEAP_SIZE +#define JERRY_GLOBAL_HEAP_SIZE (512) +#endif /* !defined (JERRY_GLOBAL_HEAP_SIZE) */ + +/** + * The allowed heap usage limit until next garbage collection, in bytes. + * + * If value is 0, the default is 1/32 of JERRY_HEAP_SIZE + */ +#ifndef JERRY_GC_LIMIT +#define JERRY_GC_LIMIT 0 +#endif /* !defined (JERRY_GC_LIMIT) */ + +/** + * Maximum stack usage size in kilobytes + * + * Note: This feature cannot be used when 'detect_stack_use_after_return=1' ASAN option is enabled. + * For more detailed description: + * - https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn#compatibility + * + * Default value: 0, unlimited + */ +#ifndef JERRY_STACK_LIMIT +#define JERRY_STACK_LIMIT (0) +#endif /* !defined (JERRY_STACK_LIMIT) */ + +/** + * Maximum depth of recursion during GC mark phase + * + * Default value: 8 + */ +#ifndef JERRY_GC_MARK_LIMIT +#define JERRY_GC_MARK_LIMIT (8) +#endif /* !defined (JERRY_GC_MARK_LIMIT) */ + +/** + * Enable/Disable property lookup cache. + * + * Allowed values: + * 0: Disable lookup cache. + * 1: Enable lookup cache. + * + * Default value: 1 + */ +#ifndef JERRY_LCACHE +#define JERRY_LCACHE 1 +#endif /* !defined (JERRY_LCACHE) */ + +/** + * Enable/Disable function toString operation. + * + * Allowed values: + * 0: Disable function toString operation. + * 1: Enable function toString operation. + * + * Default value: 0 + */ +#ifndef JERRY_FUNCTION_TO_STRING +#define JERRY_FUNCTION_TO_STRING 0 +#endif /* !defined (JERRY_FUNCTION_TO_STRING) */ + +/** + * Enable/Disable line-info management inside the engine. + * + * Allowed values: + * 0: Disable line-info in the engine. + * 1: Enable line-info management. + * + * Default value: 0 + */ +#ifndef JERRY_LINE_INFO +#define JERRY_LINE_INFO 0 +#endif /* !defined (JERRY_LINE_INFO) */ + +/** + * Enable/Disable logging inside the engine. + * + * Allowed values: + * 0: Disable internal logging. + * 1: Enable internal logging. + * + * Default value: 0 + */ +#ifndef JERRY_LOGGING +#define JERRY_LOGGING 0 +#endif /* !defined (JERRY_LOGGING) */ + +/** + * Enable/Disable gc call before every allocation. + * + * Allowed values: + * 0: Disable gc call before each allocation. + * 1: Enable and force gc call before each allocation. + * + * Default value: 0 + * Warning!: This is an advanced option and will slow down the engine! + * Only enable it for debugging purposes. + */ +#ifndef JERRY_MEM_GC_BEFORE_EACH_ALLOC +#define JERRY_MEM_GC_BEFORE_EACH_ALLOC 0 +#endif /* !defined (JERRY_MEM_GC_BEFORE_EACH_ALLOC) */ + +/** + * Use 32-bit/64-bit float for ecma-numbers + * This option is for expert use only! + * + * Allowed values: + * 1: use 64-bit floating point number mode + * 0: use 32-bit floating point number mode + * + * Default value: 1 + */ +#ifndef JERRY_NUMBER_TYPE_FLOAT64 +#define JERRY_NUMBER_TYPE_FLOAT64 1 +#endif /* !defined (JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Enable/Disable the JavaScript parser. + * + * Allowed values: + * 0: Disable the JavaScript parser and all related functionallity. + * 1: Enable the JavaScript parser. + * + * Default value: 1 + */ +#ifndef JERRY_PARSER +#define JERRY_PARSER 1 +#endif /* !defined (JERRY_PARSER) */ + +/** + * Enable/Disable JerryScript byte code dump functions during parsing. + * To dump the JerryScript byte code the engine must be initialized with opcodes + * display flag. This option does not influence RegExp byte code dumps. + * + * Allowed values: + * 0: Disable all bytecode dump functions. + * 1: Enable bytecode dump functions. + * + * Default value: 0 + */ +#ifndef JERRY_PARSER_DUMP_BYTE_CODE +#define JERRY_PARSER_DUMP_BYTE_CODE 0 +#endif /* defined (JERRY_PARSER_DUMP_BYTE_CODE) */ + +/** + * Enable/Disable ECMA property hashmap. + * + * Allowed values: + * 0: Disable property hasmap. + * 1: Enable property hashmap. + * + * Default value: 1 + */ +#ifndef JERRY_PROPERTY_HASHMAP +#define JERRY_PROPERTY_HASHMAP 1 +#endif /* !defined (JERRY_PROPERTY_HASHMAP) */ + +/** + * Enables/disables the Promise event callbacks + * + * Default value: 0 + */ +#ifndef JERRY_PROMISE_CALLBACK +#define JERRY_PROMISE_CALLBACK 0 +#endif /* !defined (JERRY_PROMISE_CALLBACK) */ + +/** + * Enable/Disable byte code dump functions for RegExp objects. + * To dump the RegExp byte code the engine must be initialized with + * regexp opcodes display flag. This option does not influence the + * JerryScript byte code dumps. + * + * Allowed values: + * 0: Disable all bytecode dump functions. + * 1: Enable bytecode dump functions. + * + * Default value: 0 + */ +#ifndef JERRY_REGEXP_DUMP_BYTE_CODE +#define JERRY_REGEXP_DUMP_BYTE_CODE 0 +#endif /* !defined (JERRY_REGEXP_DUMP_BYTE_CODE) */ + +/** + * Enables/disables the RegExp strict mode + * + * Default value: 0 + */ +#ifndef JERRY_REGEXP_STRICT_MODE +#define JERRY_REGEXP_STRICT_MODE 0 +#endif /* !defined (JERRY_REGEXP_STRICT_MODE) */ + +/** + * Enable/Disable the snapshot execution functions. + * + * Allowed values: + * 0: Disable snapshot execution. + * 1: Enable snapshot execution. + * + * Default value: 0 + */ +#ifndef JERRY_SNAPSHOT_EXEC +#define JERRY_SNAPSHOT_EXEC 0 +#endif /* !defined (JERRY_SNAPSHOT_EXEC) */ + +/** + * Enable/Disable the snapshot save functions. + * + * Allowed values: + * 0: Disable snapshot save functions. + * 1: Enable snapshot save functions. + */ +#ifndef JERRY_SNAPSHOT_SAVE +#define JERRY_SNAPSHOT_SAVE 0 +#endif /* !defined (JERRY_SNAPSHOT_SAVE) */ + +/** + * Enable/Disable usage of system allocator. + * + * Allowed values: + * 0: Disable usage of system allocator. + * 1: Enable usage of system allocator. + * + * Default value: 0 + */ +#ifndef JERRY_SYSTEM_ALLOCATOR +#define JERRY_SYSTEM_ALLOCATOR 0 +#endif /* !defined (JERRY_SYSTEM_ALLOCATOR) */ + +/** + * Enables/disables the unicode case conversion in the engine. + * By default Unicode case conversion is enabled. + */ +#ifndef JERRY_UNICODE_CASE_CONVERSION +#define JERRY_UNICODE_CASE_CONVERSION 1 +#endif /* !defined (JERRY_UNICODE_CASE_CONVERSION) */ + +/** + * Configures if the internal memory allocations are exposed to Valgrind or not. + * + * Allowed values: + * 0: Disable the Valgrind specific memory allocation notifications. + * 1: Enable the Valgrind specific allocation notifications. + */ +#ifndef JERRY_VALGRIND +#define JERRY_VALGRIND 0 +#endif /* !defined (JERRY_VALGRIND) */ + +/** + * Enable/Disable the vm execution stop callback function. + * + * Allowed values: + * 0: Disable vm exec stop callback support. + * 1: Enable vm exec stop callback support. + */ +#ifndef JERRY_VM_HALT +#define JERRY_VM_HALT 0 +#endif /* !defined (JERRY_VM_HALT) */ + +/** + * Enable/Disable the vm throw callback function. + * + * Allowed values: + * 0: Disable vm throw callback support. + * 1: Enable vm throw callback support. + */ +#ifndef JERRY_VM_THROW +#define JERRY_VM_THROW 0 +#endif /* !defined (JERRY_VM_THROW) */ + +/** + * Advanced section configurations. + */ + +/** + * Allow configuring attributes on a few constant data inside the engine. + * + * One of the main usages: + * Normally compilers store const(ant)s in ROM. Thus saving RAM. + * But if your compiler does not support it then the directive below can force it. + * + * For the moment it is mainly meant for the following targets: + * - ESP8266 + * + * Example configuration for moving (some) constatns into a given section: + * # define JERRY_ATTR_CONST_DATA __attribute__((section(".rodata.const"))) + */ +#ifndef JERRY_ATTR_CONST_DATA +#define JERRY_ATTR_CONST_DATA +#endif /* !defined (JERRY_ATTR_CONST_DATA) */ + +/** + * The JERRY_ATTR_GLOBAL_HEAP allows adding extra attributes for the Jerry global heap. + * + * Example on how to move the global heap into it's own section: + * #define JERRY_ATTR_GLOBAL_HEAP __attribute__((section(".text.globalheap"))) + */ +#ifndef JERRY_ATTR_GLOBAL_HEAP +#define JERRY_ATTR_GLOBAL_HEAP +#endif /* !defined (JERRY_ATTR_GLOBAL_HEAP) */ + +/** + * Sanity check for macros to see if the values are 0 or 1 + * + * If a new feature is added this should be updated. + */ +/** + * Check base builtins. + */ +#if (JERRY_BUILTIN_ANNEXB != 0) && (JERRY_BUILTIN_ANNEXB != 1) +#error "Invalid value for JERRY_BUILTIN_ANNEXB macro." +#endif /* (JERRY_BUILTIN_ANNEXB != 0) && (JERRY_BUILTIN_ANNEXB != 1) */ +#if (JERRY_BUILTIN_ARRAY != 0) && (JERRY_BUILTIN_ARRAY != 1) +#error "Invalid value for JERRY_BUILTIN_ARRAY macro." +#endif /* (JERRY_BUILTIN_ARRAY != 0) && (JERRY_BUILTIN_ARRAY != 1) */ +#if (JERRY_BUILTIN_BOOLEAN != 0) && (JERRY_BUILTIN_BOOLEAN != 1) +#error "Invalid value for JERRY_BUILTIN_BOOLEAN macro." +#endif /* (JERRY_BUILTIN_BOOLEAN != 0) && (JERRY_BUILTIN_BOOLEAN != 1) */ +#if (JERRY_BUILTIN_DATE != 0) && (JERRY_BUILTIN_DATE != 1) +#error "Invalid value for JERRY_BUILTIN_DATE macro." +#endif /* (JERRY_BUILTIN_DATE != 0) && (JERRY_BUILTIN_DATE != 1) */ +#if (JERRY_BUILTIN_ERRORS != 0) && (JERRY_BUILTIN_ERRORS != 1) +#error "Invalid value for JERRY_BUILTIN_ERRORS macro." +#endif /* (JERRY_BUILTIN_ERRORS != 0) && (JERRY_BUILTIN_ERRORS != 1) */ +#if (JERRY_BUILTIN_MATH != 0) && (JERRY_BUILTIN_MATH != 1) +#error "Invalid value for JERRY_BUILTIN_MATH macro." +#endif /* (JERRY_BUILTIN_MATH != 0) && (JERRY_BUILTIN_MATH != 1) */ +#if (JERRY_BUILTIN_NUMBER != 0) && (JERRY_BUILTIN_NUMBER != 1) +#error "Invalid value for JERRY_BUILTIN_NUMBER macro." +#endif /* (JERRY_BUILTIN_NUMBER != 0) && (JERRY_BUILTIN_NUMBER != 1) */ +#if (JERRY_BUILTIN_REGEXP != 0) && (JERRY_BUILTIN_REGEXP != 1) +#error "Invalid value for JERRY_BUILTIN_REGEXP macro." +#endif /* (JERRY_BUILTIN_REGEXP != 0) && (JERRY_BUILTIN_REGEXP != 1) */ +#if (JERRY_BUILTIN_STRING != 0) && (JERRY_BUILTIN_STRING != 1) +#error "Invalid value for JERRY_BUILTIN_STRING macro." +#endif /* (JERRY_BUILTIN_STRING != 0) && (JERRY_BUILTIN_STRING != 1) */ +#if (JERRY_BUILTINS != 0) && (JERRY_BUILTINS != 1) +#error "Invalid value for JERRY_BUILTINS macro." +#endif /* (JERRY_BUILTINS != 0) && (JERRY_BUILTINS != 1) */ +#if (JERRY_BUILTIN_REALMS != 0) && (JERRY_BUILTIN_REALMS != 1) +#error "Invalid value for JERRY_BUILTIN_REALMS macro." +#endif /* (JERRY_BUILTIN_REALMS != 0) && (JERRY_BUILTIN_REALMS != 1) */ +#if (JERRY_BUILTIN_DATAVIEW != 0) && (JERRY_BUILTIN_DATAVIEW != 1) +#error "Invalid value for JERRY_BUILTIN_DATAVIEW macro." +#endif /* (JERRY_BUILTIN_DATAVIEW != 0) && (JERRY_BUILTIN_DATAVIEW != 1) */ +#if (JERRY_BUILTIN_GLOBAL_THIS != 0) && (JERRY_BUILTIN_GLOBAL_THIS != 1) +#error "Invalid value for JERRY_BUILTIN_GLOBAL_THIS macro." +#endif /* (JERRY_BUILTIN_GLOBAL_THIS != 0) && (JERRY_BUILTIN_GLOBAL_THIS != 1) */ +#if (JERRY_BUILTIN_REFLECT != 0) && (JERRY_BUILTIN_REFLECT != 1) +#error "Invalid value for JERRY_BUILTIN_REFLECT macro." +#endif /* (JERRY_BUILTIN_REFLECT != 0) && (JERRY_BUILTIN_REFLECT != 1) */ +#if (JERRY_BUILTIN_WEAKREF != 0) && (JERRY_BUILTIN_WEAKREF != 1) +#error "Invalid value for JERRY_BUILTIN_WEAKREF macro." +#endif /* (JERRY_BUILTIN_WEAKREF != 0) && (JERRY_BUILTIN_WEAKREF != 1) */ +#if (JERRY_BUILTIN_PROXY != 0) && (JERRY_BUILTIN_PROXY != 1) +#error "Invalid value for JERRY_BUILTIN_PROXY macro." +#endif /* (JERRY_BUILTIN_PROXY != 0) && (JERRY_BUILTIN_PROXY != 1) */ +#if (JERRY_BUILTIN_TYPEDARRAY != 0) && (JERRY_BUILTIN_TYPEDARRAY != 1) +#error "Invalid value for JERRY_BUILTIN_TYPEDARRAY macro." +#endif /* (JERRY_BUILTIN_TYPEDARRAY != 0) && (JERRY_BUILTIN_TYPEDARRAY != 1) */ +#if (JERRY_BUILTIN_SHAREDARRAYBUFFER != 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER != 1) +#error "Invalid value for JERRY_BUILTIN_SHAREDARRAYBUFFER macro." +#endif /* (JERRY_BUILTIN_SHAREDARRAYBUFFER != 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER != 1) */ +#if (JERRY_BUILTIN_ATOMICS != 0) && (JERRY_BUILTIN_ATOMICS != 1) +#error "Invalid value for JERRY_BUILTIN_ATOMICS macro." +#endif /* (JERRY_BUILTIN_ATOMICS != 0) && (JERRY_BUILTIN_ATOMICS != 1) */ +#if (JERRY_BUILTIN_BIGINT != 0) && (JERRY_BUILTIN_BIGINT != 1) +#error "Invalid value for JERRY_BUILTIN_BIGINT macro." +#endif /* (JERRY_BUILTIN_BIGINT != 0) && (JERRY_BUILTIN_BIGINT != 1) */ +#if (JERRY_MODULE_SYSTEM != 0) && (JERRY_MODULE_SYSTEM != 1) +#error "Invalid value for JERRY_MODULE_SYSTEM macro." +#endif /* (JERRY_MODULE_SYSTEM != 0) && (JERRY_MODULE_SYSTEM != 1) */ +#if (JERRY_BUILTIN_TYPEDARRAY == 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER == 1) +#error "JERRY_BUILTIN_TYPEDARRAY should be enabled too to enable JERRY_BUILTIN_SHAREDARRAYBUFFER macro." +#endif /* (JERRY_BUILTIN_TYPEDARRAY == 0) && (JERRY_BUILTIN_SHAREDARRAYBUFFER == 1) */ +#if (JERRY_BUILTIN_SHAREDARRAYBUFFER == 0) && (JERRY_BUILTIN_ATOMICS == 1) +#error "JERRY_BUILTIN_SHAREDARRAYBUFFER should be enabled too to enable JERRY_BUILTIN_ATOMICS macro." +#endif /* (JERRY_BUILTIN_SHAREDARRAYBUFFER == 0) && (JERRY_BUILTIN_ATOMICS == 1) */ + +/** + * Internal options. + */ +#if (JERRY_CPOINTER_32_BIT != 0) && (JERRY_CPOINTER_32_BIT != 1) +#error "Invalid value for 'JERRY_CPOINTER_32_BIT' macro." +#endif /* (JERRY_CPOINTER_32_BIT != 0) && (JERRY_CPOINTER_32_BIT != 1) */ +#if (JERRY_ERROR_MESSAGES != 0) && (JERRY_ERROR_MESSAGES != 1) +#error "Invalid value for 'JERRY_ERROR_MESSAGES' macro." +#endif /* (JERRY_ERROR_MESSAGES != 0) && (JERRY_ERROR_MESSAGES != 1) */ +#if (JERRY_EXTERNAL_CONTEXT != 0) && (JERRY_EXTERNAL_CONTEXT != 1) +#error "Invalid value for 'JERRY_EXTERNAL_CONTEXT' macro." +#endif /* (JERRY_EXTERNAL_CONTEXT != 0) && (JERRY_EXTERNAL_CONTEXT != 1) */ +#if JERRY_GLOBAL_HEAP_SIZE <= 0 +#error "Invalid value for 'JERRY_GLOBAL_HEAP_SIZE' macro." +#endif /* JERRY_GLOBAL_HEAP_SIZE <= 0 */ +#if JERRY_GC_LIMIT < 0 +#error "Invalid value for 'JERRY_GC_LIMIT' macro." +#endif /* JERRY_GC_LIMIT < 0 */ +#if JERRY_STACK_LIMIT < 0 +#error "Invalid value for 'JERRY_STACK_LIMIT' macro." +#endif /* JERRY_STACK_LIMIT < 0 */ +#if JERRY_GC_MARK_LIMIT < 0 +#error "Invalid value for 'JERRY_GC_MARK_LIMIT' macro." +#endif /* JERRY_GC_MARK_LIMIT < 0 */ +#if (JERRY_LCACHE != 0) && (JERRY_LCACHE != 1) +#error "Invalid value for 'JERRY_LCACHE' macro." +#endif /* (JERRY_LCACHE != 0) && (JERRY_LCACHE != 1) */ +#if (JERRY_FUNCTION_TO_STRING != 0) && (JERRY_FUNCTION_TO_STRING != 1) +#error "Invalid value for 'JERRY_FUNCTION_TO_STRING' macro." +#endif /* (JERRY_FUNCTION_TO_STRING != 0) && (JERRY_FUNCTION_TO_STRING != 1) */ +#if (JERRY_LINE_INFO != 0) && (JERRY_LINE_INFO != 1) +#error "Invalid value for 'JERRY_LINE_INFO' macro." +#endif /* (JERRY_LINE_INFO != 0) && (JERRY_LINE_INFO != 1) */ +#if (JERRY_LOGGING != 0) && (JERRY_LOGGING != 1) +#error "Invalid value for 'JERRY_LOGGING' macro." +#endif /* (JERRY_LOGGING != 0) && (JERRY_LOGGING != 1) */ +#if (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 0) && (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 1) +#error "Invalid value for 'JERRY_MEM_GC_BEFORE_EACH_ALLOC' macro." +#endif /* (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 0) && (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 1) */ +#if (JERRY_NUMBER_TYPE_FLOAT64 != 0) && (JERRY_NUMBER_TYPE_FLOAT64 != 1) +#error "Invalid value for 'JERRY_NUMBER_TYPE_FLOAT64' macro." +#endif /* (JERRY_NUMBER_TYPE_FLOAT64 != 0) && (JERRY_NUMBER_TYPE_FLOAT64 != 1) */ +#if (JERRY_PARSER != 0) && (JERRY_PARSER != 1) +#error "Invalid value for 'JERRY_PARSER' macro." +#endif /* (JERRY_PARSER != 0) && (JERRY_PARSER != 1) */ +#if (JERRY_PARSER_DUMP_BYTE_CODE != 0) && (JERRY_PARSER_DUMP_BYTE_CODE != 1) +#error "Invalid value for 'JERRY_PARSER_DUMP_BYTE_CODE' macro." +#endif /* (JERRY_PARSER_DUMP_BYTE_CODE != 0) && (JERRY_PARSER_DUMP_BYTE_CODE != 1) */ +#if (JERRY_PROPERTY_HASHMAP != 0) && (JERRY_PROPERTY_HASHMAP != 1) +#error "Invalid value for 'JERRY_PROPERTY_HASHMAP' macro." +#endif /* (JERRY_PROPERTY_HASHMAP != 0) && (JERRY_PROPERTY_HASHMAP != 1) */ +#if (JERRY_PROMISE_CALLBACK != 0) && (JERRY_PROMISE_CALLBACK != 1) +#error "Invalid value for 'JERRY_PROMISE_CALLBACK' macro." +#endif /* (JERRY_PROMISE_CALLBACK != 0) && (JERRY_PROMISE_CALLBACK != 1) */ +#if (JERRY_REGEXP_DUMP_BYTE_CODE != 0) && (JERRY_REGEXP_DUMP_BYTE_CODE != 1) +#error "Invalid value for 'JERRY_REGEXP_DUMP_BYTE_CODE' macro." +#endif /* (JERRY_REGEXP_DUMP_BYTE_CODE != 0) && (JERRY_REGEXP_DUMP_BYTE_CODE != 1) */ +#if (JERRY_REGEXP_STRICT_MODE != 0) && (JERRY_REGEXP_STRICT_MODE != 1) +#error "Invalid value for 'JERRY_REGEXP_STRICT_MODE' macro." +#endif /* (JERRY_REGEXP_STRICT_MODE != 0) && (JERRY_REGEXP_STRICT_MODE != 1) */ +#if (JERRY_SNAPSHOT_EXEC != 0) && (JERRY_SNAPSHOT_EXEC != 1) +#error "Invalid value for 'JERRY_SNAPSHOT_EXEC' macro." +#endif /* (JERRY_SNAPSHOT_EXEC != 0) && (JERRY_SNAPSHOT_EXEC != 1) */ +#if (JERRY_SNAPSHOT_SAVE != 0) && (JERRY_SNAPSHOT_SAVE != 1) +#error "Invalid value for 'JERRY_SNAPSHOT_SAVE' macro." +#endif /* (JERRY_SNAPSHOT_SAVE != 0) && (JERRY_SNAPSHOT_SAVE != 1) */ +#if (JERRY_SYSTEM_ALLOCATOR != 0) && (JERRY_SYSTEM_ALLOCATOR != 1) +#error "Invalid value for 'JERRY_SYSTEM_ALLOCATOR' macro." +#endif /* (JERRY_SYSTEM_ALLOCATOR != 0) && (JERRY_SYSTEM_ALLOCATOR != 1) */ +#if (JERRY_UNICODE_CASE_CONVERSION != 0) && (JERRY_UNICODE_CASE_CONVERSION != 1) +#error "Invalid value for 'JERRY_UNICODE_CASE_CONVERSION' macro." +#endif /* (JERRY_UNICODE_CASE_CONVERSION != 0) && (JERRY_UNICODE_CASE_CONVERSION != 1) */ +#if (JERRY_VALGRIND != 0) && (JERRY_VALGRIND != 1) +#error "Invalid value for 'JERRY_VALGRIND' macro." +#endif /* (JERRY_VALGRIND != 0) && (JERRY_VALGRIND != 1) */ +#if (JERRY_VM_HALT != 0) && (JERRY_VM_HALT != 1) +#error "Invalid value for 'JERRY_VM_HALT' macro." +#endif /* (JERRY_VM_HALT != 0) && (JERRY_VM_HALT != 1) */ +#if (JERRY_VM_THROW != 0) && (JERRY_VM_THROW != 1) +#error "Invalid value for 'JERRY_VM_THROW' macro." +#endif /* (JERRY_VM_THROW != 0) && (JERRY_VM_THROW != 1) */ + +/** + * Cross component requirements check. + */ + +/** + * The date module can only use the float 64 number types. + */ +#if JERRY_BUILTIN_DATE && !JERRY_NUMBER_TYPE_FLOAT64 +#error "Date does not support float32" +#endif /* JERRY_BUILTIN_DATE && !JERRY_NUMBER_TYPE_FLOAT64 */ + +/** + * Source name related types into a single guard + */ +#if JERRY_LINE_INFO || JERRY_ERROR_MESSAGES || JERRY_MODULE_SYSTEM +#define JERRY_SOURCE_NAME 1 +#else /* !(JERRY_LINE_INFO || JERRY_ERROR_MESSAGES || JERRY_MODULE_SYSTEM) */ +#define JERRY_SOURCE_NAME 0 +#endif /* JERRY_LINE_INFO || JERRY_ERROR_MESSAGES || JERRY_MODULE_SYSTEM */ + +#endif /* !JERRYSCRIPT_CONFIG_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-compiler.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-compiler.h new file mode 100644 index 00000000..071ad0bf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-compiler.h @@ -0,0 +1,187 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_COMPILER_H +#define JERRYSCRIPT_COMPILER_H + +#ifdef __cplusplus +#define JERRY_C_API_BEGIN extern "C" { +#define JERRY_C_API_END } +#else /* !__cplusplus */ +#define JERRY_C_API_BEGIN +#define JERRY_C_API_END +#endif /* __cplusplus */ + +JERRY_C_API_BEGIN + +/** \addtogroup jerry-compiler Jerry compiler compatibility components + * @{ + */ + +#ifdef __GNUC__ + +/* + * Compiler-specific macros relevant for GCC. + */ +#define JERRY_ATTR_ALIGNED(ALIGNMENT) __attribute__ ((aligned (ALIGNMENT))) +#define JERRY_ATTR_CONST __attribute__ ((const)) +#define JERRY_ATTR_DEPRECATED __attribute__ ((deprecated)) +#define JERRY_ATTR_FORMAT(...) __attribute__ ((format (__VA_ARGS__))) +#define JERRY_ATTR_HOT __attribute__ ((hot)) +#define JERRY_ATTR_NOINLINE __attribute__ ((noinline)) +#define JERRY_ATTR_NORETURN __attribute__ ((noreturn)) +#define JERRY_ATTR_PURE __attribute__ ((pure)) +#define JERRY_ATTR_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) +#define JERRY_ATTR_WEAK __attribute__ ((weak)) + +#define JERRY_WEAK_SYMBOL_SUPPORT + +#ifndef JERRY_LIKELY +#define JERRY_LIKELY(x) __builtin_expect (!!(x), 1) +#endif /* !JERRY_LIKELY */ + +#ifndef JERRY_UNLIKELY +#define JERRY_UNLIKELY(x) __builtin_expect (!!(x), 0) +#endif /* !JERRY_UNLIKELY */ + +#endif /* __GNUC__ */ + +#ifdef _MSC_VER + +/* + * Compiler-specific macros relevant for Microsoft Visual C/C++ Compiler. + */ +#define JERRY_ATTR_DEPRECATED __declspec (deprecated) +#define JERRY_ATTR_NOINLINE __declspec (noinline) +#define JERRY_ATTR_NORETURN __declspec (noreturn) + +/* + * Microsoft Visual C/C++ Compiler doesn't support for VLA, using _alloca + * instead. + */ +void *__cdecl _alloca (size_t _Size); +#define JERRY_VLA(type, name, size) type *name = (type *) (_alloca (sizeof (type) * (size))) + +#endif /* _MSC_VER */ + +/* + * Default empty definitions for all compiler-specific macros. Define any of + * these in a guarded block above (e.g., as for GCC) to fine tune compilation + * for your own compiler. */ + +/** + * Function attribute to align function to given number of bytes. + */ +#ifndef JERRY_ATTR_ALIGNED +#define JERRY_ATTR_ALIGNED(ALIGNMENT) +#endif /* !JERRY_ATTR_ALIGNED */ + + +/** + * Function attribute to declare that function has no effect except the return + * value and it only depends on parameters. + */ +#ifndef JERRY_ATTR_CONST +#define JERRY_ATTR_CONST +#endif /* !JERRY_ATTR_CONST */ + +/** + * Function attribute to trigger warning if deprecated function is called. + */ +#ifndef JERRY_ATTR_DEPRECATED +#define JERRY_ATTR_DEPRECATED +#endif /* !JERRY_ATTR_DEPRECATED */ + +/** + * Function attribute to declare that function is variadic and takes a format + * string and some arguments as parameters. + */ +#ifndef JERRY_ATTR_FORMAT +#define JERRY_ATTR_FORMAT(...) +#endif /* !JERRY_ATTR_FORMAT */ + +/** + * Function attribute to predict that function is a hot spot, and therefore + * should be optimized aggressively. + */ +#ifndef JERRY_ATTR_HOT +#define JERRY_ATTR_HOT +#endif /* !JERRY_ATTR_HOT */ + +/** + * Function attribute not to inline function ever. + */ +#ifndef JERRY_ATTR_NOINLINE +#define JERRY_ATTR_NOINLINE +#endif /* !JERRY_ATTR_NOINLINE */ + +/** + * Function attribute to declare that function never returns. + */ +#ifndef JERRY_ATTR_NORETURN +#define JERRY_ATTR_NORETURN +#endif /* !JERRY_ATTR_NORETURN */ + +/** + * Function attribute to declare that function has no effect except the return + * value and it only depends on parameters and global variables. + */ +#ifndef JERRY_ATTR_PURE +#define JERRY_ATTR_PURE +#endif /* !JERRY_ATTR_PURE */ + +/** + * Function attribute to trigger warning if function's caller doesn't use (e.g., + * check) the return value. + */ +#ifndef JERRY_ATTR_WARN_UNUSED_RESULT +#define JERRY_ATTR_WARN_UNUSED_RESULT +#endif /* !JERRY_ATTR_WARN_UNUSED_RESULT */ + +/** + * Function attribute to declare a function a weak symbol + */ +#ifndef JERRY_ATTR_WEAK +#define JERRY_ATTR_WEAK +#endif /* !JERRY_ATTR_WEAK */ + +/** + * Helper to predict that a condition is likely. + */ +#ifndef JERRY_LIKELY +#define JERRY_LIKELY(x) (x) +#endif /* !JERRY_LIKELY */ + +/** + * Helper to predict that a condition is unlikely. + */ +#ifndef JERRY_UNLIKELY +#define JERRY_UNLIKELY(x) (x) +#endif /* !JERRY_UNLIKELY */ + +/** + * Helper to declare (or mimic) a C99 variable-length array. + */ +#ifndef JERRY_VLA +#define JERRY_VLA(type, name, size) type name[size] +#endif /* !JERRY_VLA */ + +/** + * @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_COMPILER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-core.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-core.h new file mode 100644 index 00000000..b034b109 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-core.h @@ -0,0 +1,1209 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_CORE_H +#define JERRYSCRIPT_CORE_H + +#include "jerryscript-types.h" + +JERRY_C_API_BEGIN + +/** + * @defgroup jerry-api JerryScript public API + * @{ + */ + +/** + * @defgroup jerry-api-general General functions + * @{ + */ + +/** + * @defgroup jerry-api-general-conext Context management + * @{ + */ +void jerry_init (jerry_init_flag_t flags); +void jerry_cleanup (void); + +void *jerry_context_data (const jerry_context_data_manager_t *manager_p); + +jerry_value_t jerry_current_realm (void); +jerry_value_t jerry_set_realm (jerry_value_t realm); +/** + * jerry-api-general-conext @} + */ + +/** + * @defgroup jerry-api-general-heap Heap management + * @{ + */ +void *jerry_heap_alloc (jerry_size_t size); +void jerry_heap_free (void *mem_p, jerry_size_t size); + +bool jerry_heap_stats (jerry_heap_stats_t *out_stats_p); +void jerry_heap_gc (jerry_gc_mode_t mode); + +bool jerry_foreach_live_object (jerry_foreach_live_object_cb_t callback, void *user_data); +bool jerry_foreach_live_object_with_info (const jerry_object_native_info_t *native_info_p, + jerry_foreach_live_object_with_info_cb_t callback, + void *user_data_p); +/** + * jerry-api-general-heap @} + */ + +/** + * @defgroup jerry-api-general-misc Miscellaneous + * @{ + */ + +void JERRY_ATTR_FORMAT (printf, 2, 3) jerry_log (jerry_log_level_t level, const char *format_p, ...); +void jerry_log_set_level (jerry_log_level_t level); +bool jerry_validate_string (const jerry_char_t *buffer_p, jerry_size_t buffer_size, jerry_encoding_t encoding); +bool JERRY_ATTR_CONST jerry_feature_enabled (const jerry_feature_t feature); +void jerry_register_magic_strings (const jerry_char_t *const *ext_strings_p, + uint32_t count, + const jerry_length_t *str_lengths_p); +/** + * jerry-api-general-misc @} + */ + +/** + * jerry-api-general @} + */ + +/** + * @defgroup jerry-api-code Scripts and Executables + * @{ + */ + +/** + * @defgroup jerry-api-code-parse Parsing + * @{ + */ +jerry_value_t jerry_parse (const jerry_char_t *source_p, size_t source_size, const jerry_parse_options_t *options_p); +jerry_value_t jerry_parse_value (const jerry_value_t source, const jerry_parse_options_t *options_p); +/** + * jerry-api-code-parse @} + */ + +/** + * @defgroup jerry-api-code-exec Execution + * @{ + */ +jerry_value_t jerry_eval (const jerry_char_t *source_p, size_t source_size, uint32_t flags); +jerry_value_t jerry_run (const jerry_value_t script); +jerry_value_t jerry_run_jobs (void); +/** + * jerry-api-code-exec @} + */ + +/** + * @defgroup jerry-api-code-sourceinfo Source information + * @{ + */ +jerry_value_t jerry_source_name (const jerry_value_t value); +jerry_value_t jerry_source_user_value (const jerry_value_t value); +jerry_source_info_t *jerry_source_info (const jerry_value_t value); +void jerry_source_info_free (jerry_source_info_t *source_info_p); +/** + * jerry-api-code-sourceinfo @} + */ + +/** + * @defgroup jerry-api-code-cb Callbacks + * @{ + */ +void jerry_halt_handler (uint32_t interval, jerry_halt_cb_t callback, void *user_p); +/** + * jerry-api-code-cb @} + */ + +/** + * jerry-api-code @} + */ + +/** + * @defgroup jerry-api-backtrace Backtraces + * @{ + */ + +/** + * @defgroup jerry-api-backtrace-capture Capturing + * @{ + */ +jerry_value_t jerry_backtrace (uint32_t max_depth); +void jerry_backtrace_capture (jerry_backtrace_cb_t callback, void *user_p); +/** + * jerry-api-backtrace-capture @} + */ + +/** + * @defgroup jerry-api-backtrace-frame Frames + * @{ + */ +jerry_frame_type_t jerry_frame_type (const jerry_frame_t *frame_p); +const jerry_value_t *jerry_frame_callee (jerry_frame_t *frame_p); +const jerry_value_t *jerry_frame_this (jerry_frame_t *frame_p); +const jerry_frame_location_t *jerry_frame_location (jerry_frame_t *frame_p); +bool jerry_frame_is_strict (jerry_frame_t *frame_p); +/** + * jerry-api-backtrace-frame @} + */ + +/** + * jerry-api-backtrace @} + */ + +/** + * @defgroup jerry-api-value Values + * @{ + */ + +/* Reference management */ +jerry_value_t JERRY_ATTR_WARN_UNUSED_RESULT jerry_value_copy (const jerry_value_t value); +void jerry_value_free (jerry_value_t value); + +/** + * @defgroup jerry-api-value-checks Type inspection + * @{ + */ +jerry_type_t jerry_value_type (const jerry_value_t value); +bool jerry_value_is_exception (const jerry_value_t value); +bool jerry_value_is_abort (const jerry_value_t value); + +bool jerry_value_is_undefined (const jerry_value_t value); +bool jerry_value_is_null (const jerry_value_t value); +bool jerry_value_is_boolean (const jerry_value_t value); +bool jerry_value_is_true (const jerry_value_t value); +bool jerry_value_is_false (const jerry_value_t value); + +bool jerry_value_is_number (const jerry_value_t value); +bool jerry_value_is_bigint (const jerry_value_t value); + +bool jerry_value_is_string (const jerry_value_t value); +bool jerry_value_is_symbol (const jerry_value_t value); + +bool jerry_value_is_object (const jerry_value_t value); +bool jerry_value_is_array (const jerry_value_t value); +bool jerry_value_is_promise (const jerry_value_t value); +bool jerry_value_is_proxy (const jerry_value_t value); +bool jerry_value_is_arraybuffer (const jerry_value_t value); +bool jerry_value_is_shared_arraybuffer (const jerry_value_t value); +bool jerry_value_is_dataview (const jerry_value_t value); +bool jerry_value_is_typedarray (const jerry_value_t value); + +bool jerry_value_is_constructor (const jerry_value_t value); +bool jerry_value_is_function (const jerry_value_t value); +bool jerry_value_is_async_function (const jerry_value_t value); + +bool jerry_value_is_error (const jerry_value_t value); +/** + * jerry-api-value-checks @} + */ + +/** + * @defgroup jerry-api-value-coerce Coercion + * @{ + */ +bool jerry_value_to_boolean (const jerry_value_t value); +jerry_value_t jerry_value_to_number (const jerry_value_t value); +jerry_value_t jerry_value_to_object (const jerry_value_t value); +jerry_value_t jerry_value_to_primitive (const jerry_value_t value); +jerry_value_t jerry_value_to_string (const jerry_value_t value); +jerry_value_t jerry_value_to_bigint (const jerry_value_t value); + +double jerry_value_as_number (const jerry_value_t value); +double jerry_value_as_integer (const jerry_value_t value); +int32_t jerry_value_as_int32 (const jerry_value_t value); +uint32_t jerry_value_as_uint32 (const jerry_value_t value); +/** + * jerry-api-value-coerce @} + */ + +/** + * @defgroup jerry-api-value-op Operations + * @{ + */ +jerry_value_t jerry_binary_op (jerry_binary_op_t operation, const jerry_value_t lhs, const jerry_value_t rhs); + +/** + * jerry-api-value-op @} + */ + +/** + * jerry-api-value @} + */ + +/** + * @defgroup jerry-api-exception Exceptions + * @{ + */ + +/** + * @defgroup jerry-api-exception-ctor Constructors + * @{ + */ +jerry_value_t jerry_throw (jerry_error_t type, const jerry_value_t message); +jerry_value_t jerry_throw_sz (jerry_error_t type, const char *message_p); +jerry_value_t jerry_throw_value (jerry_value_t value, bool take_ownership); +jerry_value_t jerry_throw_abort (jerry_value_t value, bool take_ownership); +/** + * jerry-api-exception-ctor @} + */ + +/** + * @defgroup jerry-api-exception-op Operations + * @{ + */ +void jerry_exception_allow_capture (jerry_value_t value, bool allow_capture); +/** + * jerry-api-exception-op @} + */ + +/** + * @defgroup jerry-api-exception-get Getters + * @{ + */ +jerry_value_t jerry_exception_value (jerry_value_t value, bool free_exception); +bool jerry_exception_is_captured (const jerry_value_t value); +/** + * jerry-api-exception-get @} + */ + +/** + * @defgroup jerry-api-exception-cb Callbacks + * @{ + */ +void jerry_on_throw (jerry_throw_cb_t callback, void *user_p); +/** + * jerry-api-exception-cb @} + */ + +/** + * jerry-api-error @} + */ + +/** + * @defgroup jerry-api-primitives Primitive types + * @{ + */ + +/** + * @defgroup jerry-api-undefined Undefined + * @{ + */ + +/** + * @defgroup jerry-api-undefined-ctor Constructors + * @{ + */ + +jerry_value_t JERRY_ATTR_CONST jerry_undefined (void); + +/** + * jerry-api-undefined-ctor @} + */ + +/** + * jerry-api-undefined @} + */ + +/** + * @defgroup jerry-api-null Null + * @{ + */ + +/** + * @defgroup jerry-api-null-ctor Constructors + * @{ + */ + +jerry_value_t JERRY_ATTR_CONST jerry_null (void); + +/** + * jerry-api-null-ctor @} + */ + +/** + * jerry-api-null @} + */ + +/** + * @defgroup jerry-api-boolean Boolean + * @{ + */ + +/** + * @defgroup jerry-api-boolean-ctor Constructors + * @{ + */ + +jerry_value_t JERRY_ATTR_CONST jerry_boolean (bool value); + +/** + * jerry-api-boolean-ctor @} + */ + +/** + * jerry-api-boolean @} + */ + +/** + * @defgroup jerry-api-number Number + * @{ + */ + +/** + * @defgroup jerry-api-number-ctor Number + * @{ + */ + +jerry_value_t jerry_number (double value); +jerry_value_t jerry_infinity (bool sign); +jerry_value_t jerry_nan (void); + +/** + * jerry-api-number-ctor @} + */ + +/** + * jerry-api-number @} + */ + +/** + * @defgroup jerry-api-bigint BigInt + * @{ + */ + +/** + * @defgroup jerry-api-bigint-ctor Constructors + * @{ + */ +jerry_value_t jerry_bigint (const uint64_t *digits_p, uint32_t digit_count, bool sign); +/** + * jerry-api-bigint-ctor @} + */ + +/** + * @defgroup jerry-api-bigint-get Getters + * @{ + */ +uint32_t jerry_bigint_digit_count (const jerry_value_t value); +/** + * jerry-api-bigint-get @} + */ + +/** + * @defgroup jerry-api-bigint-op Operations + * @{ + */ +void jerry_bigint_to_digits (const jerry_value_t value, uint64_t *digits_p, uint32_t digit_count, bool *sign_p); +/** + * jerry-api-bigint-get @} + */ + +/** + * jerry-api-bigint @} + */ + +/** + * @defgroup jerry-api-string String + * @{ + */ + +/** + * @defgroup jerry-api-string-ctor Constructors + * @{ + */ +jerry_value_t jerry_string (const jerry_char_t *buffer_p, jerry_size_t buffer_size, jerry_encoding_t encoding); +jerry_value_t jerry_string_sz (const char *str_p); +jerry_value_t jerry_string_external (const jerry_char_t *buffer_p, jerry_size_t buffer_size, void *user_p); +jerry_value_t jerry_string_external_sz (const char *str_p, void *user_p); +/** + * jerry-api-string-cotr @} + */ + +/** + * @defgroup jerry-api-string-get Getters + * @{ + */ +jerry_size_t jerry_string_size (const jerry_value_t value, jerry_encoding_t encoding); +jerry_length_t jerry_string_length (const jerry_value_t value); +void *jerry_string_user_ptr (const jerry_value_t value, bool *is_external); +/** + * jerry-api-string-get @} + */ + +/** + * @defgroup jerry-api-string-op Operations + * @{ + */ +jerry_size_t jerry_string_substr (const jerry_value_t value, jerry_length_t start, jerry_length_t end); +jerry_size_t jerry_string_to_buffer (const jerry_value_t value, + jerry_encoding_t encoding, + jerry_char_t *buffer_p, + jerry_size_t buffer_size); +void jerry_string_iterate (const jerry_value_t value, + jerry_encoding_t encoding, + jerry_string_iterate_cb_t callback, + void *user_p); +/** + * jerry-api-string-op @} + */ + +/** + * @defgroup jerry-api-string-cb Callbacks + * @{ + */ +void jerry_string_external_on_free (jerry_external_string_free_cb_t callback); +/** + * jerry-api-string-cb @} + */ + +/** + * jerry-api-string @} + */ + +/** + * @defgroup jerry-api-symbol Symbol + * @{ + */ + +/** + * @defgroup jerry-api-symbol-ctor Constructors + * @{ + */ +jerry_value_t jerry_symbol (jerry_well_known_symbol_t symbol); +jerry_value_t jerry_symbol_with_description (const jerry_value_t value); +/** + * jerry-api-symbol-ctor @} + */ + +/** + * @defgroup jerry-api-symbol-get Getters + * @{ + */ +jerry_value_t jerry_symbol_description (const jerry_value_t symbol); +jerry_value_t jerry_symbol_descriptive_string (const jerry_value_t symbol); +/** + * jerry-api-symbol-get @} + */ + +/** + * jerry-api-symbol @} + */ + +/** + * jerry-api-primitives @} + */ + +/** + * @defgroup jerry-api-objects Objects + * @{ + */ + +/** + * @defgroup jerry-api-object-ctor Constructors + * @{ + */ +jerry_value_t jerry_object (void); +/** + * jerry-api-object-ctor @} + */ + +/** + * @defgroup jerry-api-object-get Getters + * @{ + */ + +jerry_object_type_t jerry_object_type (const jerry_value_t object); +jerry_value_t jerry_object_proto (const jerry_value_t object); +jerry_value_t jerry_object_keys (const jerry_value_t object); +jerry_value_t jerry_object_property_names (const jerry_value_t object, jerry_property_filter_t filter); + +/** + * jerry-api-object-get @} + */ + +/** + * @defgroup jerry-api-object-op Operations + * @{ + */ + +jerry_value_t jerry_object_set_proto (jerry_value_t object, const jerry_value_t proto); +bool jerry_object_foreach (const jerry_value_t object, jerry_object_property_foreach_cb_t foreach_p, void *user_data_p); + +/** + * @defgroup jerry-api-object-op-set Set + * @{ + */ +jerry_value_t jerry_object_set (jerry_value_t object, const jerry_value_t key, const jerry_value_t value); +jerry_value_t jerry_object_set_sz (jerry_value_t object, const char *key_p, const jerry_value_t value); +jerry_value_t jerry_object_set_index (jerry_value_t object, uint32_t index, const jerry_value_t value); +jerry_value_t jerry_object_define_own_prop (jerry_value_t object, + const jerry_value_t key, + const jerry_property_descriptor_t *prop_desc_p); +bool jerry_object_set_internal (jerry_value_t object, const jerry_value_t key, const jerry_value_t value); +void jerry_object_set_native_ptr (jerry_value_t object, + const jerry_object_native_info_t *native_info_p, + void *native_pointer_p); +/** + * jerry-api-object-op-set @} + */ + +/** + * @defgroup jerry-api-object-op-has Has + * @{ + */ +jerry_value_t jerry_object_has (const jerry_value_t object, const jerry_value_t key); +jerry_value_t jerry_object_has_sz (const jerry_value_t object, const char *key_p); +jerry_value_t jerry_object_has_own (const jerry_value_t object, const jerry_value_t key); +bool jerry_object_has_internal (const jerry_value_t object, const jerry_value_t key); +bool jerry_object_has_native_ptr (const jerry_value_t object, const jerry_object_native_info_t *native_info_p); +/** + * jerry-api-object-op-has @} + */ + +/** + * @defgroup jerry-api-object-op-get Get + * @{ + */ +jerry_value_t jerry_object_get (const jerry_value_t object, const jerry_value_t key); +jerry_value_t jerry_object_get_sz (const jerry_value_t object, const char *key_p); +jerry_value_t jerry_object_get_index (const jerry_value_t object, uint32_t index); +jerry_value_t jerry_object_get_own_prop (const jerry_value_t object, + const jerry_value_t key, + jerry_property_descriptor_t *prop_desc_p); +jerry_value_t jerry_object_get_internal (const jerry_value_t object, const jerry_value_t key); +void *jerry_object_get_native_ptr (const jerry_value_t object, const jerry_object_native_info_t *native_info_p); + +jerry_value_t jerry_object_find_own (const jerry_value_t object, + const jerry_value_t key, + const jerry_value_t receiver, + bool *found_p); +/** + * jerry-api-object-op-get @} + */ + +/** + * @defgroup jerry-api-object-op-del Delete + * @{ + */ +jerry_value_t jerry_object_delete (jerry_value_t object, const jerry_value_t key); +jerry_value_t jerry_object_delete_sz (const jerry_value_t object, const char *key_p); +jerry_value_t jerry_object_delete_index (jerry_value_t object, uint32_t index); +bool jerry_object_delete_internal (jerry_value_t object, const jerry_value_t key); +bool jerry_object_delete_native_ptr (jerry_value_t object, const jerry_object_native_info_t *native_info_p); +/** + * jerry-api-object-op-del @} + */ + +/** + * jerry-api-object-op @} + */ + +/** + * @defgroup jerry-api-object-prop-desc Property descriptors + * @{ + */ + +/** + * @defgroup jerry-api-object-prop-desc-ctor Constructors + * @{ + */ +jerry_property_descriptor_t jerry_property_descriptor (void); +jerry_value_t jerry_property_descriptor_from_object (const jerry_value_t obj_value, + jerry_property_descriptor_t *out_prop_desc_p); +/** + * jerry-api-object-prop-desc-ctor @} + */ + +/** + * @defgroup jerry-api-object-prop-desc-op Operations + * @{ + */ +void jerry_property_descriptor_free (jerry_property_descriptor_t *prop_desc_p); +jerry_value_t jerry_property_descriptor_to_object (const jerry_property_descriptor_t *src_prop_desc_p); +/** + * jerry-api-object-prop-desc-op @} + */ + +/** + * jerry-api-object-prop-desc @} + */ + +/** + * @defgroup jerry-api-object-native-ptr Native pointers + * @{ + */ + +/** + * @defgroup jerry-api-object-native-ptr-op Operations + * @{ + */ +void jerry_native_ptr_init (void *native_pointer_p, const jerry_object_native_info_t *native_info_p); +void jerry_native_ptr_free (void *native_pointer_p, const jerry_object_native_info_t *native_info_p); +void jerry_native_ptr_set (jerry_value_t *reference_p, const jerry_value_t value); +/** + * jerry-api-object-native-ptr-op @} + */ + +/** + * jerry-api-object-native-ptr @} + */ + +/** + * @defgroup jerry-api-array Array + * @{ + */ + +/** + * @defgroup jerry-api-array-ctor Constructors + * @{ + */ +jerry_value_t jerry_array (jerry_length_t length); +/** + * jerry-api-array-ctor @} + */ + +/** + * @defgroup jerry-api-array-get Getters + * @{ + */ +jerry_length_t jerry_array_length (const jerry_value_t value); +/** + * jerry-api-array-get @} + */ + +/** + * jerry-api-array @} + */ + +/** + * @defgroup jerry-api-arraybuffer ArrayBuffer + * @{ + */ + +/** + * @defgroup jerry-api-arraybuffer-ctor Constructors + * @{ + */ +jerry_value_t jerry_arraybuffer (const jerry_length_t size); +jerry_value_t jerry_arraybuffer_external (uint8_t *buffer_p, jerry_length_t size, void *user_p); +/** + * jerry-api-arraybuffer-ctor @} + */ + +/** + * @defgroup jerry-api-arraybuffer-get Getters + * @{ + */ +jerry_size_t jerry_arraybuffer_size (const jerry_value_t value); +uint8_t *jerry_arraybuffer_data (const jerry_value_t value); +bool jerry_arraybuffer_is_detachable (const jerry_value_t value); +bool jerry_arraybuffer_has_buffer (const jerry_value_t value); +/** + * jerry-api-arraybuffer-get @} + */ + +/** + * @defgroup jerry-api-arraybuffer-op Operations + * @{ + */ +jerry_size_t +jerry_arraybuffer_read (const jerry_value_t value, jerry_size_t offset, uint8_t *buffer_p, jerry_size_t buffer_size); +jerry_size_t +jerry_arraybuffer_write (jerry_value_t value, jerry_size_t offset, const uint8_t *buffer_p, jerry_size_t buffer_size); +jerry_value_t jerry_arraybuffer_detach (jerry_value_t value); +void jerry_arraybuffer_heap_allocation_limit (jerry_size_t limit); +/** + * jerry-api-arraybuffer-op @} + */ + +/** + * @defgroup jerry-api-arraybuffer-cb Callbacks + * @{ + */ +void jerry_arraybuffer_allocator (jerry_arraybuffer_allocate_cb_t allocate_callback, + jerry_arraybuffer_free_cb_t free_callback, + void *user_p); +/** + * jerry-api-arraybuffer-cb @} + */ + +/** + * jerry-api-arraybuffer @} + */ + +/** + * @defgroup jerry-api-sharedarraybuffer SharedArrayBuffer + * @{ + */ + +/** + * @defgroup jerry-api-sharedarraybuffer-ctor Constructors + * @{ + */ +jerry_value_t jerry_shared_arraybuffer (jerry_size_t size); +jerry_value_t jerry_shared_arraybuffer_external (uint8_t *buffer_p, jerry_size_t buffer_size, void *user_p); +/** + * jerry-api-sharedarraybuffer-ctor @} + */ + +/** + * jerry-api-sharedarraybuffer @} + */ + +/** + * @defgroup jerry-api-dataview DataView + * @{ + */ + +/** + * @defgroup jerry-api-dataview-ctor Constructors + * @{ + */ +jerry_value_t jerry_dataview (const jerry_value_t value, jerry_size_t byte_offset, jerry_size_t byte_length); +/** + * jerry-api-dataview-ctr @} + */ + +/** + * @defgroup jerry-api-dataview-get Getters + * @{ + */ +jerry_value_t +jerry_dataview_buffer (const jerry_value_t dataview, jerry_size_t *byte_offset, jerry_size_t *byte_length); +/** + * jerry-api-dataview-get @} + */ + +/** + * jerry-api-dataview @} + */ + +/** + * @defgroup jerry-api-typedarray TypedArray + * @{ + */ + +/** + * @defgroup jerry-api-typedarray-ctor Constructors + * @{ + */ +jerry_value_t jerry_typedarray (jerry_typedarray_type_t type, jerry_length_t length); +jerry_value_t jerry_typedarray_with_buffer (jerry_typedarray_type_t type, const jerry_value_t arraybuffer); +jerry_value_t jerry_typedarray_with_buffer_span (jerry_typedarray_type_t type, + const jerry_value_t arraybuffer, + jerry_size_t byte_offset, + jerry_size_t byte_length); +/** + * jerry-api-typedarray-ctor @} + */ + +/** + * @defgroup jerry-api-typedarray-get Getters + * @{ + */ +jerry_typedarray_type_t jerry_typedarray_type (const jerry_value_t value); +jerry_length_t jerry_typedarray_length (const jerry_value_t value); +jerry_value_t jerry_typedarray_buffer (const jerry_value_t value, jerry_size_t *byte_offset, jerry_size_t *byte_length); +/** + * jerry-api-typedarray-get @} + */ + +/** + * jerry-api-typedarray @} + */ + +/** + * @defgroup jerry-api-iterator Iterator + * @{ + */ + +/** + * @defgroup jerry-api-iterator-get Getters + * @{ + */ +jerry_iterator_type_t jerry_iterator_type (const jerry_value_t value); +/** + * jerry-api-iterator-get @} + */ + +/** + * jerry-api-iterator @} + */ + +/** + * @defgroup jerry-api-function Function + * @{ + */ + +/** + * @defgroup jerry-api-function-ctor Constructors + * @{ + */ +jerry_value_t jerry_function_external (jerry_external_handler_t handler); +/** + * jerry-api-function-ctor @} + */ + +/** + * @defgroup jerry-api-function-get Getters + * @{ + */ +jerry_function_type_t jerry_function_type (const jerry_value_t value); +bool jerry_function_is_dynamic (const jerry_value_t value); +/** + * jerry-api-function-get @} + */ + +/** + * @defgroup jerry-api-function-op Operations + * @{ + */ +jerry_value_t jerry_call (const jerry_value_t function, + const jerry_value_t this_value, + const jerry_value_t *args_p, + jerry_size_t args_count); +jerry_value_t jerry_construct (const jerry_value_t function, const jerry_value_t *args_p, jerry_size_t args_count); +/** + * jerry-api-function-op @} + */ + +/** + * jerry-api-function @} + */ + +/** + * @defgroup jerry-api-proxy Proxy + * @{ + */ + +/** + * @defgroup jerry-api-proxy-ctor Constructors + * @{ + */ +jerry_value_t jerry_proxy (const jerry_value_t target, const jerry_value_t handler); +jerry_value_t jerry_proxy_custom (const jerry_value_t target, const jerry_value_t handler, uint32_t flags); +/** + * jerry-api-function-proxy-ctor @} + */ + +/** + * @defgroup jerry-api-proxy-get Getters + * @{ + */ +jerry_value_t jerry_proxy_target (const jerry_value_t value); +jerry_value_t jerry_proxy_handler (const jerry_value_t value); +/** + * jerry-api-function-proxy-get @} + */ + +/** + * jerry-api-proxy @} + */ + +/** + * @defgroup jerry-api-promise Promise + * @{ + */ + +/** + * @defgroup jerry-api-promise-ctor Constructors + * @{ + */ +jerry_value_t jerry_promise (void); +/** + * jerry-api-promise-ctor @} + */ + +/** + * @defgroup jerry-api-promise-get Getters + * @{ + */ +jerry_value_t jerry_promise_result (const jerry_value_t promise); +jerry_promise_state_t jerry_promise_state (const jerry_value_t promise); +/** + * jerry-api-promise-get @} + */ + +/** + * @defgroup jerry-api-promise-op Operations + * @{ + */ +jerry_value_t jerry_promise_resolve (jerry_value_t promise, const jerry_value_t argument); +jerry_value_t jerry_promise_reject (jerry_value_t promise, const jerry_value_t argument); +/** + * jerry-api-promise-op @} + */ + +/** + * @defgroup jerry-api-promise-cb Callbacks + * @{ + */ +void jerry_promise_on_event (jerry_promise_event_filter_t filters, jerry_promise_event_cb_t callback, void *user_p); +/** + * jerry-api-promise-cb @} + */ + +/** + * jerry-api-promise @} + */ + +/** + * @defgroup jerry-api-container Map, Set, WeakMap, WeakSet + * @{ + */ + +/** + * @defgroup jerry-api-container-ctor Constructors + * @{ + */ +jerry_value_t jerry_container (jerry_container_type_t container_type, + const jerry_value_t *arguments_p, + jerry_length_t argument_count); +/** + * jerry-api-promise-ctor @} + */ + +/** + * @defgroup jerry-api-container-get Getters + * @{ + */ +jerry_container_type_t jerry_container_type (const jerry_value_t value); +/** + * jerry-api-container-get @} + */ + +/** + * @defgroup jerry-api-container-op Operations + * @{ + */ +jerry_value_t jerry_container_to_array (const jerry_value_t value, bool *is_key_value_p); +jerry_value_t jerry_container_op (jerry_container_op_t operation, + jerry_value_t container, + const jerry_value_t *arguments, + uint32_t argument_count); +/** + * jerry-api-container-op @} + */ + +/** + * jerry-api-container @} + */ + +/** + * @defgroup jerry-api-regexp RegExp + * @{ + */ + +/** + * @defgroup jerry-api-regexp-ctor Constructors + * @{ + */ +jerry_value_t jerry_regexp (const jerry_value_t pattern, uint16_t flags); +jerry_value_t jerry_regexp_sz (const char *pattern_p, uint16_t flags); +/** + * jerry-api-regexp-ctor @} + */ + +/** + * jerry-api-regexp @} + */ + +/** + * @defgroup jerry-api-error Error + * @{ + */ + +/** + * @defgroup jerry-api-error-ctor Constructors + * @{ + */ +jerry_value_t jerry_error (jerry_error_t type, const jerry_value_t message); +jerry_value_t jerry_error_sz (jerry_error_t type, const char *message_p); +/** + * jerry-api-error-ctor @} + */ + +/** + * @defgroup jerry-api-error-get Getters + * @{ + */ +jerry_error_t jerry_error_type (jerry_value_t value); +/** + * jerry-api-error-get @} + */ + +/** + * @defgroup jerry-api-error-cb Callbacks + * @{ + */ +void jerry_error_on_created (jerry_error_object_created_cb_t callback, void *user_p); +/** + * jerry-api-error-cb @} + */ + +/** + * jerry-api-error @} + */ + +/** + * jerry-api-objects @} + */ + +/** + * @defgroup jerry-api-json JSON + * @{ + */ + +/** + * @defgroup jerry-api-json-op Operations + * @{ + */ +jerry_value_t jerry_json_parse (const jerry_char_t *string_p, jerry_size_t string_size); +jerry_value_t jerry_json_stringify (const jerry_value_t object); +/** + * jerry-api-json-op @} + */ + +/** + * jerry-api-json @} + */ + +/** + * @defgroup jerry-api-module Modules + * @{ + */ + +/** + * @defgroup jerry-api-module-get Getters + * @{ + */ +jerry_module_state_t jerry_module_state (const jerry_value_t module); +size_t jerry_module_request_count (const jerry_value_t module); +jerry_value_t jerry_module_request (const jerry_value_t module, size_t request_index); +jerry_value_t jerry_module_namespace (const jerry_value_t module); +/** + * jerry-api-module-get @} + */ + +/** + * @defgroup jerry-api-module-op Operations + * @{ + */ + +/** + * Resolve and parse a module file + * + * @param specifier: module request specifier string. + * @param referrer: parent module. + * @param user_p: user specified pointer. + * + * @return module object if resolving is successful, error otherwise. + */ +jerry_value_t jerry_module_resolve (const jerry_value_t specifier, const jerry_value_t referrer, void *user_p); + +jerry_value_t jerry_module_link (const jerry_value_t module, jerry_module_resolve_cb_t callback, void *user_p); +jerry_value_t jerry_module_evaluate (const jerry_value_t module); + +/** + * Release known modules in the current context. If realm parameter is supplied, cleans up modules native to that realm + * only. This function should be called by the user application when the module database in the current context is no + * longer needed. + * + * @param realm: release only those modules which realm value is equal to this argument. + */ +void jerry_module_cleanup (const jerry_value_t realm); + +/** + * jerry-api-module-op @} + */ + +/** + * @defgroup jerry-api-module-native Native modules + * @{ + */ +jerry_value_t jerry_native_module (jerry_native_module_evaluate_cb_t callback, + const jerry_value_t *const exports_p, + size_t export_count); +jerry_value_t jerry_native_module_get (const jerry_value_t native_module, const jerry_value_t export_name); +jerry_value_t +jerry_native_module_set (jerry_value_t native_module, const jerry_value_t export_name, const jerry_value_t value); +/** + * jerry-api-module-native @} + */ + +/** + * @defgroup jerry-api-module-cb Callbacks + * @{ + */ +void jerry_module_on_state_changed (jerry_module_state_changed_cb_t callback, void *user_p); +void jerry_module_on_import_meta (jerry_module_import_meta_cb_t callback, void *user_p); +void jerry_module_on_import (jerry_module_import_cb_t callback, void *user_p); +/** + * jerry-api-module-cb @} + */ + +/** + * jerry-api-module @} + */ + +/** + * @defgroup jerry-api-realm Realms + * @{ + */ + +/** + * @defgroup jerry-api-realm-ctor Constructors + * @{ + */ +jerry_value_t jerry_realm (void); +/** + * jerry-api-realm-ctor @} + */ + +/** + * @defgroup jerry-api-realm-get Getters + * @{ + */ +jerry_value_t jerry_realm_this (jerry_value_t realm); +/** + * jerry-api-realm-ctor @} + */ + +/** + * @defgroup jerry-api-realm-op Operation + * @{ + */ +jerry_value_t jerry_realm_set_this (jerry_value_t realm, jerry_value_t this_value); +/** + * jerry-api-realm-op @} + */ + +/** + * jerry-api-realm @} + */ + +/** + * jerry-api @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_CORE_H */ + +/* vim: set fdm=marker fmr=@{,@}: */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-port.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-port.h new file mode 100644 index 00000000..1b882488 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-port.h @@ -0,0 +1,313 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_PORT_H +#define JERRYSCRIPT_PORT_H + +#include "jerryscript-types.h" + +JERRY_C_API_BEGIN + +/** + * @defgroup jerry-port JerryScript Port API + * @{ + */ + +/** + * @defgroup jerry-port-process Process management API + * + * It is questionable whether a library should be able to terminate an + * application. However, as of now, we only have the concept of completion + * code around jerry_parse and jerry_run. Most of the other API functions + * have no way of signaling an error. So, we keep the termination approach + * with this port function. + * + * @{ + */ + +/** + * Error codes that can be passed by the engine when calling jerry_port_fatal + */ +typedef enum +{ + JERRY_FATAL_OUT_OF_MEMORY = 10, /**< Out of memory */ + JERRY_FATAL_REF_COUNT_LIMIT = 12, /**< Reference count limit reached */ + JERRY_FATAL_DISABLED_BYTE_CODE = 13, /**< Executed disabled instruction */ + JERRY_FATAL_UNTERMINATED_GC_LOOPS = 14, /**< Garbage collection loop limit reached */ + JERRY_FATAL_FAILED_ASSERTION = 120 /**< Assertion failed */ +} jerry_fatal_code_t; + +/** + * Signal the port that the process experienced a fatal failure from which it cannot + * recover. + * + * A libc-based port may implement this with exit() or abort(), or both. + * + * @param code: the cause of the error. + * @return This function is expected to not return. + */ +void JERRY_ATTR_NORETURN jerry_port_fatal (jerry_fatal_code_t code); + +/** + * Make the process sleep for a given time. + * + * This port function can be called by jerry-core when JERRY_DEBUGGER is enabled. + * Otherwise this function is not used. + * + * @param sleep_time: milliseconds to sleep. + */ +void jerry_port_sleep (uint32_t sleep_time); + +/** + * jerry-port-process @} + */ + +/** + * @defgroup jerry-port-context External Context API + * @{ + */ + +/** + * Allocate a new context for the engine. + * + * This port function is called by jerry_init when JERRY_EXTERNAL_CONTEXT is enabled. Otherwise this function is not + * used. + * + * The engine will pass the size required for the context structure. An implementation must make sure to + * allocate at least this amount. + * + * Excess allocated space will be used as the engine heap when JerryScript is configured to use it's internal allocator, + * this can be used to control the internal heap size. + * + * NOTE: The allocated memory must be pointer-aligned, otherwise the behavior is undefined. + * + * @param context_size: the size of the internal context structure + * + * @return total size of the allocated buffer + */ +size_t jerry_port_context_alloc (size_t context_size); + +/** + * Get the currently active context of the engine. + * + * This port function is called by jerry-core when JERRY_EXTERNAL_CONTEXT is enabled. + * Otherwise this function is not used. + * + * @return the pointer to the currently used engine context. + */ +struct jerry_context_t *jerry_port_context_get (void); + +/** + * Free the currently used context. + * + * This port function is called by jerry_cleanup when JERRY_EXTERNAL_CONTEXT is enabled. + * Otherwise this function is not used. + */ +void jerry_port_context_free (void); + +/** + * jerry-port-context @} + */ + +/** + * @defgroup jerry-port-io I/O API + * @{ + */ + +/** + * Display or log a debug/error message. + * + * The message is passed as a zero-terminated string. Messages may be logged in parts, which + * will result in multiple calls to this functions. The implementation should consider + * this before appending or prepending strings to the argument. + * + * This function is called with messages coming from the jerry engine as + * the result of some abnormal operation or describing its internal operations + * (e.g., data structure dumps or tracing info). + * + * The implementation can decide whether error and debug messages are logged to + * the console, or saved to a database or to a file. + */ +void jerry_port_log (const char *message_p); + +/** + * Print a single character to standard output. + * + * This port function is never called from jerry-core directly, it is only used by jerry-ext components to print + * information. + * + * @param byte: the byte to print. + */ +void jerry_port_print_byte (jerry_char_t byte); + +/** + * Print a buffer to standard output + * + * This port function is never called from jerry-core directly, it is only used by jerry-ext components to print + * information. + * + * @param buffer_p: input buffer + * @param buffer_size: data size + */ +void jerry_port_print_buffer (const jerry_char_t *buffer_p, jerry_size_t buffer_size); + +/** + * Read a line from standard input. + * + * The implementation should allocate storage necessary for the string. The result string should include the ending line + * terminator character(s) and should be zero terminated. + * + * An implementation may return NULL to signal that the end of input is reached, or an error occured. + * + * When a non-NULL value is returned, the caller will pass the returned value to `jerry_port_line_free` when the line is + * no longer needed. This can be used to finalize dynamically allocated buffers if necessary. + * + * This port function is never called from jerry-core directly, it is only used by some jerry-ext components that + * require user input. + * + * @param out_size_p: size of the input string in bytes, excluding terminating zero byte + * + * @return pointer to the buffer storing the string, + * or NULL if end of input + */ +jerry_char_t *jerry_port_line_read (jerry_size_t *out_size_p); + +/** + * Free a line buffer allocated by jerry_port_line_read + * + * @param buffer_p: buffer returned by jerry_port_line_read + */ +void jerry_port_line_free (jerry_char_t *buffer_p); + +/** + * jerry-port-io @} + */ + +/** + * @defgroup jerry-port-fd Filesystem API + * @{ + */ + +/** + * Canonicalize a file path. + * + * If possible, the implementation should resolve symbolic links and other directory references found in the input path, + * and create a fully canonicalized file path as the result. + * + * The function may return with NULL in case an error is encountered, in which case the calling operation will not + * proceed. + * + * The implementation should allocate storage for the result path as necessary. Non-NULL return values will be passed + * to `jerry_port_path_free` when the result is no longer needed by the caller, which can be used to finalize + * dynamically allocated buffers. + * + * NOTE: The implementation must not return directly with the input, as the input buffer is released after the call. + * + * @param path_p: zero-terminated string containing the input path + * @param path_size: size of the input path string in bytes, excluding terminating zero + * + * @return buffer with the normalized path if the operation is successful, + * NULL otherwise + */ +jerry_char_t *jerry_port_path_normalize (const jerry_char_t *path_p, jerry_size_t path_size); + +/** + * Free a path buffer returned by jerry_port_path_normalize. + * + * @param path_p: the path buffer to free + */ +void jerry_port_path_free (jerry_char_t *path_p); + +/** + * Get the offset of the basename component in the input path. + * + * The implementation should return the offset of the first character after the last path separator found in the path. + * This is used by the caller to split the path into a directory name and a file name. + * + * @param path_p: input zero-terminated path string + * + * @return offset of the basename component in the input path + */ +jerry_size_t jerry_port_path_base (const jerry_char_t *path_p); + +/** + * Open a source file and read the content into a buffer. + * + * When the source file is no longer needed by the caller, the returned pointer will be passed to + * `jerry_port_source_free`, which can be used to finalize the buffer. + * + * @param file_name_p: Path that points to the source file in the filesystem. + * @param out_size_p: The opened file's size in bytes. + * + * @return pointer to the buffer which contains the content of the file. + */ +jerry_char_t *jerry_port_source_read (const char *file_name_p, jerry_size_t *out_size_p); + +/** + * Free a source file buffer. + * + * @param buffer_p: buffer returned by jerry_port_source_read + */ +void jerry_port_source_free (jerry_char_t *buffer_p); + +/** + * jerry-port-fs @} + */ + +/** + * @defgroup jerry-port-date Date API + * @{ + */ + +/** + * Get local time zone adjustment in milliseconds for the given input time. + * + * The argument is a time value representing milliseconds since unix epoch. + * + * Ideally, this function should satisfy the stipulations applied to LocalTZA + * in section 21.4.1.7 of the ECMAScript version 12.0, as if called with isUTC true. + * + * This port function can be called by jerry-core when JERRY_BUILTIN_DATE is enabled. + * Otherwise this function is not used. + * + * @param unix_ms: time value in milliseconds since unix epoch + * + * @return local time offset in milliseconds applied to UTC for the given time value + */ +int32_t jerry_port_local_tza (double unix_ms); + +/** + * Get the current system time in UTC. + * + * This port function is called by jerry-core when JERRY_BUILTIN_DATE is enabled. + * It can also be used in the implementing application to initialize the random number generator. + * + * @return milliseconds since Unix epoch + */ +double jerry_port_current_time (void); + +/** + * jerry-port-date @} + */ + +/** + * jerry-port @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_PORT_H */ + +/* vim: set fdm=marker fmr=@{,@}: */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-types.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-types.h new file mode 100644 index 00000000..4f0b98f0 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript-types.h @@ -0,0 +1,865 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_TYPES_H +#define JERRYSCRIPT_TYPES_H + +#include +#include +#include + +#include "jerryscript-compiler.h" + +JERRY_C_API_BEGIN + +/** + * @defgroup jerry-api-types JerryScript public API types + * @{ + */ + +/** + * JerryScript init flags. + */ +typedef enum +{ + JERRY_INIT_EMPTY = (0u), /**< empty flag set */ + JERRY_INIT_SHOW_OPCODES = (1u << 0), /**< dump byte-code to log after parse */ + JERRY_INIT_SHOW_REGEXP_OPCODES = (1u << 1), /**< dump regexp byte-code to log after compilation */ + JERRY_INIT_MEM_STATS = (1u << 2), /**< dump memory statistics */ +} jerry_init_flag_t; + +/** + * Jerry log levels. The levels are in severity order + * where the most serious levels come first. + */ +typedef enum +{ + JERRY_LOG_LEVEL_ERROR = 0u, /**< the engine will terminate after the message is printed */ + JERRY_LOG_LEVEL_WARNING = 1u, /**< a request is aborted, but the engine continues its operation */ + JERRY_LOG_LEVEL_DEBUG = 2u, /**< debug messages from the engine, low volume */ + JERRY_LOG_LEVEL_TRACE = 3u /**< detailed info about engine internals, potentially high volume */ +} jerry_log_level_t; + +/** + * JerryScript API Error object types. + */ +typedef enum +{ + JERRY_ERROR_NONE = 0, /**< No Error */ + + JERRY_ERROR_COMMON, /**< Error */ + JERRY_ERROR_EVAL, /**< EvalError */ + JERRY_ERROR_RANGE, /**< RangeError */ + JERRY_ERROR_REFERENCE, /**< ReferenceError */ + JERRY_ERROR_SYNTAX, /**< SyntaxError */ + JERRY_ERROR_TYPE, /**< TypeError */ + JERRY_ERROR_URI, /**< URIError */ + JERRY_ERROR_AGGREGATE /**< AggregateError */ +} jerry_error_t; + +/** + * JerryScript feature types. + */ +typedef enum +{ + JERRY_FEATURE_CPOINTER_32_BIT, /**< 32 bit compressed pointers */ + JERRY_FEATURE_ERROR_MESSAGES, /**< error messages */ + JERRY_FEATURE_JS_PARSER, /**< js-parser */ + JERRY_FEATURE_HEAP_STATS, /**< memory statistics */ + JERRY_FEATURE_PARSER_DUMP, /**< parser byte-code dumps */ + JERRY_FEATURE_REGEXP_DUMP, /**< regexp byte-code dumps */ + JERRY_FEATURE_SNAPSHOT_SAVE, /**< saving snapshot files */ + JERRY_FEATURE_SNAPSHOT_EXEC, /**< executing snapshot files */ + JERRY_FEATURE_DEBUGGER, /**< debugging */ + JERRY_FEATURE_VM_EXEC_STOP, /**< stopping ECMAScript execution */ + JERRY_FEATURE_VM_THROW, /**< capturing ECMAScript throws */ + JERRY_FEATURE_JSON, /**< JSON support */ + JERRY_FEATURE_PROMISE, /**< promise support */ + JERRY_FEATURE_TYPEDARRAY, /**< Typedarray support */ + JERRY_FEATURE_DATE, /**< Date support */ + JERRY_FEATURE_REGEXP, /**< Regexp support */ + JERRY_FEATURE_LINE_INFO, /**< line info available */ + JERRY_FEATURE_LOGGING, /**< logging */ + JERRY_FEATURE_SYMBOL, /**< symbol support */ + JERRY_FEATURE_DATAVIEW, /**< DataView support */ + JERRY_FEATURE_PROXY, /**< Proxy support */ + JERRY_FEATURE_MAP, /**< Map support */ + JERRY_FEATURE_SET, /**< Set support */ + JERRY_FEATURE_WEAKMAP, /**< WeakMap support */ + JERRY_FEATURE_WEAKSET, /**< WeakSet support */ + JERRY_FEATURE_BIGINT, /**< BigInt support */ + JERRY_FEATURE_REALM, /**< realm support */ + JERRY_FEATURE_GLOBAL_THIS, /**< GlobalThisValue support */ + JERRY_FEATURE_PROMISE_CALLBACK, /**< Promise callback support */ + JERRY_FEATURE_MODULE, /**< Module support */ + JERRY_FEATURE_WEAKREF, /**< WeakRef support */ + JERRY_FEATURE_FUNCTION_TO_STRING, /**< function toString support */ + JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */ +} jerry_feature_t; + +/** + * GC operational modes. + */ +typedef enum +{ + JERRY_GC_PRESSURE_LOW, /**< free unused objects, but keep memory + * allocated for performance improvements + * such as property hash tables for large objects */ + JERRY_GC_PRESSURE_HIGH /**< free as much memory as possible */ +} jerry_gc_mode_t; + +/** + * Jerry regexp flags. + */ +typedef enum +{ + JERRY_REGEXP_FLAG_GLOBAL = (1u << 1), /**< Globally scan string */ + JERRY_REGEXP_FLAG_IGNORE_CASE = (1u << 2), /**< Ignore case */ + JERRY_REGEXP_FLAG_MULTILINE = (1u << 3), /**< Multiline string scan */ + JERRY_REGEXP_FLAG_STICKY = (1u << 4), /**< ECMAScript v11, 21.2.5.14 */ + JERRY_REGEXP_FLAG_UNICODE = (1u << 5), /**< ECMAScript v11, 21.2.5.17 */ + JERRY_REGEXP_FLAG_DOTALL = (1u << 6) /**< ECMAScript v11, 21.2.5.3 */ +} jerry_regexp_flags_t; + +/** + * Character type of JerryScript. + */ +typedef uint8_t jerry_char_t; + +/** + * Size type of JerryScript. + */ +typedef uint32_t jerry_size_t; + +/** + * Length type of JerryScript. + */ +typedef uint32_t jerry_length_t; + +/** + * Description of a JerryScript value. + */ +typedef uint32_t jerry_value_t; + +/** + * Option bits for jerry_parse_options_t. + */ +typedef enum +{ + JERRY_PARSE_NO_OPTS = 0, /**< no options passed */ + JERRY_PARSE_STRICT_MODE = (1 << 0), /**< enable strict mode */ + JERRY_PARSE_MODULE = (1 << 1), /**< parse source as an ECMAScript module */ + JERRY_PARSE_HAS_ARGUMENT_LIST = (1 << 2), /**< argument_list field is valid, + * this also means that function parsing will be done */ + JERRY_PARSE_HAS_SOURCE_NAME = (1 << 3), /**< source_name field is valid */ + JERRY_PARSE_HAS_START = (1 << 4), /**< start_line and start_column fields are valid */ + JERRY_PARSE_HAS_USER_VALUE = (1 << 5), /**< user_value field is valid */ +} jerry_parse_option_enable_feature_t; + +/** + * Various configuration options for parsing functions such as jerry_parse or jerry_parse_function. + */ +typedef struct +{ + uint32_t options; /**< combination of jerry_parse_option_enable_feature_t values */ + jerry_value_t argument_list; /**< function argument list if JERRY_PARSE_HAS_ARGUMENT_LIST is set in options + * Note: must be string value */ + jerry_value_t source_name; /**< source name string (usually a file name) + * if JERRY_PARSE_HAS_SOURCE_NAME is set in options + * Note: must be string value */ + uint32_t start_line; /**< start line of the source code if JERRY_PARSE_HAS_START is set in options */ + uint32_t start_column; /**< start column of the source code if JERRY_PARSE_HAS_START is set in options */ + jerry_value_t user_value; /**< user value assigned to all functions created by this script including eval + * calls executed by the script if JERRY_PARSE_HAS_USER_VALUE is set in options */ +} jerry_parse_options_t; + +/** + * Description of ECMA property descriptor. + */ +typedef enum +{ + JERRY_PROP_NO_OPTS = (0), /**< empty property descriptor */ + JERRY_PROP_IS_CONFIGURABLE = (1 << 0), /**< [[Configurable]] */ + JERRY_PROP_IS_ENUMERABLE = (1 << 1), /**< [[Enumerable]] */ + JERRY_PROP_IS_WRITABLE = (1 << 2), /**< [[Writable]] */ + + JERRY_PROP_IS_CONFIGURABLE_DEFINED = (1 << 3), /**< is [[Configurable]] defined? */ + JERRY_PROP_IS_ENUMERABLE_DEFINED = (1 << 4), /**< is [[Enumerable]] defined? */ + JERRY_PROP_IS_WRITABLE_DEFINED = (1 << 5), /**< is [[Writable]] defined? */ + + JERRY_PROP_IS_VALUE_DEFINED = (1 << 6), /**< is [[Value]] defined? */ + JERRY_PROP_IS_GET_DEFINED = (1 << 7), /**< is [[Get]] defined? */ + JERRY_PROP_IS_SET_DEFINED = (1 << 8), /**< is [[Set]] defined? */ + + JERRY_PROP_SHOULD_THROW = (1 << 9), /**< should throw on error, instead of returning with false */ +} jerry_property_descriptor_flags_t; + +/** + * Description of ECMA property descriptor. + */ +typedef struct +{ + uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ + jerry_value_t value; /**< [[Value]] */ + jerry_value_t getter; /**< [[Get]] */ + jerry_value_t setter; /**< [[Set]] */ +} jerry_property_descriptor_t; + +/** + * JerryScript object property filter options. + */ +typedef enum +{ + JERRY_PROPERTY_FILTER_ALL = 0, /**< List all property keys independently + * from key type or property value attributes + * (equivalent to Reflect.ownKeys call) */ + JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN = (1 << 0), /**< Include keys from the objects's + * prototype chain as well */ + JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE = (1 << 1), /**< Exclude property key if + * the property is non-configurable */ + JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE = (1 << 2), /**< Exclude property key if + * the property is non-enumerable */ + JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE = (1 << 3), /**< Exclude property key if + * the property is non-writable */ + JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS = (1 << 4), /**< Exclude property key if it is a string */ + JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS = (1 << 5), /**< Exclude property key if it is a symbol */ + JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES = (1 << 6), /**< Exclude property key if it is an integer index */ + JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER = (1 << 7), /**< By default integer index property keys are + * converted to string. Enabling this flags keeps + * integer index property keys as numbers. */ +} jerry_property_filter_t; + +/** + * String encoding. + */ +typedef enum +{ + JERRY_ENCODING_CESU8, /**< cesu-8 encoding */ + JERRY_ENCODING_UTF8, /**< utf-8 encoding */ +} jerry_encoding_t; + +/** + * Description of JerryScript heap memory stats. + * It is for memory profiling. + */ +typedef struct +{ + size_t version; /**< the version of the stats struct */ + size_t size; /**< heap total size */ + size_t allocated_bytes; /**< currently allocated bytes */ + size_t peak_allocated_bytes; /**< peak allocated bytes */ + size_t reserved[4]; /**< padding for future extensions */ +} jerry_heap_stats_t; + +/** + * Call related information passed to jerry_external_handler_t. + */ +typedef struct jerry_call_info_t +{ + jerry_value_t function; /**< invoked function object */ + jerry_value_t this_value; /**< this value passed to the function */ + jerry_value_t new_target; /**< current new target value, undefined for non-constructor calls */ +} jerry_call_info_t; + +/** + * Type of an external function handler. + */ +typedef jerry_value_t (*jerry_external_handler_t) (const jerry_call_info_t *call_info_p, + const jerry_value_t args_p[], + const jerry_length_t args_count); + +/** + * Native free callback of generic value types. + */ +typedef void (*jerry_value_free_cb_t) (void *native_p); + +/** + * Forward definition of jerry_object_native_info_t. + */ +struct jerry_object_native_info_t; + +/** + * Native free callback of an object. + */ +typedef void (*jerry_object_native_free_cb_t) (void *native_p, struct jerry_object_native_info_t *info_p); + +/** + * Free callback for external strings. + */ +typedef void (*jerry_external_string_free_cb_t) (jerry_char_t *string_p, jerry_size_t string_size, void *user_p); + +/** + * Decorator callback for Error objects. The decorator can create + * or update any properties of the newly created Error object. + */ +typedef void (*jerry_error_object_created_cb_t) (const jerry_value_t error_object, void *user_p); + +/** + * Callback which tells whether the ECMAScript execution should be stopped. + * + * As long as the function returns with undefined the execution continues. + * When a non-undefined value is returned the execution stops and the value + * is thrown by the engine as an exception. + * + * Note: if the function returns with a non-undefined value it + * must return with the same value for future calls. + */ +typedef jerry_value_t (*jerry_halt_cb_t) (void *user_p); + +/** + * Callback function which is called when an exception is thrown in an ECMAScript code. + * The callback should not change the exception_value. The callback is not called again + * until the value is caught. + * + * Note: the engine considers exceptions thrown by external functions as never caught. + */ +typedef void (*jerry_throw_cb_t) (const jerry_value_t exception_value, void *user_p); + +/** + * Function type applied to each unit of encoding when iterating over a string. + */ +typedef void (*jerry_string_iterate_cb_t) (uint32_t value, void *user_p); + +/** + * Function type applied for each data property of an object. + */ +typedef bool (*jerry_object_property_foreach_cb_t) (const jerry_value_t property_name, + const jerry_value_t property_value, + void *user_data_p); + +/** + * Function type applied for each object in the engine. + */ +typedef bool (*jerry_foreach_live_object_cb_t) (const jerry_value_t object, void *user_data_p); + +/** + * Function type applied for each matching object in the engine. + */ +typedef bool (*jerry_foreach_live_object_with_info_cb_t) (const jerry_value_t object, + void *object_data_p, + void *user_data_p); + +/** + * User context item manager + */ +typedef struct +{ + /** + * Callback responsible for initializing a context item, or NULL to zero out the memory. This is called lazily, the + * first time jerry_context_data () is called with this manager. + * + * @param [in] data The buffer that JerryScript allocated for the manager. The buffer is zeroed out. The size is + * determined by the bytes_needed field. The buffer is kept alive until jerry_cleanup () is called. + */ + void (*init_cb) (void *data); + + /** + * Callback responsible for deinitializing a context item, or NULL. This is called as part of jerry_cleanup (), + * right *before* the VM has been cleaned up. This is a good place to release strong references to jerry_value_t's + * that the manager may be holding. + * Note: because the VM has not been fully cleaned up yet, jerry_object_native_info_t free_cb's can still get called + * *after* all deinit_cb's have been run. See finalize_cb for a callback that is guaranteed to run *after* all + * free_cb's have been run. + * + * @param [in] data The buffer that JerryScript allocated for the manager. + */ + void (*deinit_cb) (void *data); + + /** + * Callback responsible for finalizing a context item, or NULL. This is called as part of jerry_cleanup (), + * right *after* the VM has been cleaned up and destroyed and jerry_... APIs cannot be called any more. At this point, + * all values in the VM have been cleaned up. This is a good place to clean up native state that can only be cleaned + * up at the very end when there are no more VM values around that may need to access that state. + * + * @param [in] data The buffer that JerryScript allocated for the manager. After returning from this callback, + * the data pointer may no longer be used. + */ + void (*finalize_cb) (void *data); + + /** + * Number of bytes to allocate for this manager. This is the size of the buffer that JerryScript will allocate on + * behalf of the manager. The pointer to this buffer is passed into init_cb, deinit_cb and finalize_cb. It is also + * returned from the jerry_context_data () API. + */ + size_t bytes_needed; +} jerry_context_data_manager_t; + +/** + * Function type for allocating buffer for JerryScript context. + */ +typedef void *(*jerry_context_alloc_cb_t) (size_t size, void *cb_data_p); + +/** + * Type information of a native pointer. + */ +typedef struct jerry_object_native_info_t +{ + jerry_object_native_free_cb_t free_cb; /**< the free callback of the native pointer */ + uint16_t number_of_references; /**< the number of value references which are marked by the garbage collector */ + uint16_t offset_of_references; /**< byte offset indicating the start offset of value + * references in the user allocated buffer */ +} jerry_object_native_info_t; + +/** + * An opaque declaration of the JerryScript context structure. + */ +typedef struct jerry_context_t jerry_context_t; + +/** + * Enum that contains the supported binary operation types + */ +typedef enum +{ + JERRY_BIN_OP_EQUAL = 0u, /**< equal comparison (==) */ + JERRY_BIN_OP_STRICT_EQUAL, /**< strict equal comparison (===) */ + JERRY_BIN_OP_LESS, /**< less relation (<) */ + JERRY_BIN_OP_LESS_EQUAL, /**< less or equal relation (<=) */ + JERRY_BIN_OP_GREATER, /**< greater relation (>) */ + JERRY_BIN_OP_GREATER_EQUAL, /**< greater or equal relation (>=)*/ + JERRY_BIN_OP_INSTANCEOF, /**< instanceof operation */ + JERRY_BIN_OP_ADD, /**< addition operator (+) */ + JERRY_BIN_OP_SUB, /**< subtraction operator (-) */ + JERRY_BIN_OP_MUL, /**< multiplication operator (*) */ + JERRY_BIN_OP_DIV, /**< division operator (/) */ + JERRY_BIN_OP_REM, /**< remainder operator (%) */ +} jerry_binary_op_t; + +/** + * Backtrace related types. + */ + +/** + * List of backtrace frame types returned by jerry_frame_type. + */ +typedef enum +{ + JERRY_BACKTRACE_FRAME_JS, /**< indicates that the frame is created for a JavaScript function/method */ +} jerry_frame_type_t; + +/** + * Location info retrieved by jerry_frame_location. + */ +typedef struct +{ + jerry_value_t source_name; /**< source name */ + jerry_size_t line; /**< line index */ + jerry_size_t column; /**< column index */ +} jerry_frame_location_t; + +/* + * Internal data structure for jerry_frame_t definition. + */ +struct jerry_frame_internal_t; + +/** + * Backtrace frame data passed to the jerry_backtrace_cb_t handler. + */ +typedef struct jerry_frame_internal_t jerry_frame_t; + +/** + * Callback function which is called by jerry_backtrace for each stack frame. + */ +typedef bool (*jerry_backtrace_cb_t) (jerry_frame_t *frame_p, void *user_p); + +/** + * Detailed value type related types. + */ + +/** + * JerryScript API value type information. + */ +typedef enum +{ + JERRY_TYPE_NONE = 0u, /**< no type information */ + JERRY_TYPE_UNDEFINED, /**< undefined type */ + JERRY_TYPE_NULL, /**< null type */ + JERRY_TYPE_BOOLEAN, /**< boolean type */ + JERRY_TYPE_NUMBER, /**< number type */ + JERRY_TYPE_STRING, /**< string type */ + JERRY_TYPE_OBJECT, /**< object type */ + JERRY_TYPE_FUNCTION, /**< function type */ + JERRY_TYPE_EXCEPTION, /**< exception/abort type */ + JERRY_TYPE_SYMBOL, /**< symbol type */ + JERRY_TYPE_BIGINT, /**< bigint type */ +} jerry_type_t; + +/** + * JerryScript object type information. + */ +typedef enum +{ + JERRY_OBJECT_TYPE_NONE = 0u, /**< Non object type */ + JERRY_OBJECT_TYPE_GENERIC, /**< Generic JavaScript object without any internal property */ + JERRY_OBJECT_TYPE_MODULE_NAMESPACE, /**< Namespace object */ + JERRY_OBJECT_TYPE_ARRAY, /**< Array object */ + JERRY_OBJECT_TYPE_PROXY, /**< Proxy object */ + JERRY_OBJECT_TYPE_SCRIPT, /**< Script object (see jerry_parse) */ + JERRY_OBJECT_TYPE_MODULE, /**< Module object (see jerry_parse) */ + JERRY_OBJECT_TYPE_PROMISE, /**< Promise object */ + JERRY_OBJECT_TYPE_DATAVIEW, /**< Dataview object */ + JERRY_OBJECT_TYPE_FUNCTION, /**< Function object (see jerry_function_type) */ + JERRY_OBJECT_TYPE_TYPEDARRAY, /**< %TypedArray% object (see jerry_typedarray_type) */ + JERRY_OBJECT_TYPE_ITERATOR, /**< Iterator object (see jerry_iterator_type) */ + JERRY_OBJECT_TYPE_CONTAINER, /**< Container object (see jerry_container_get_type) */ + JERRY_OBJECT_TYPE_ERROR, /**< Error object */ + JERRY_OBJECT_TYPE_ARRAYBUFFER, /**< Array buffer object */ + JERRY_OBJECT_TYPE_SHARED_ARRAY_BUFFER, /**< Shared Array Buffer object */ + + JERRY_OBJECT_TYPE_ARGUMENTS, /**< Arguments object */ + JERRY_OBJECT_TYPE_BOOLEAN, /**< Boolean object */ + JERRY_OBJECT_TYPE_DATE, /**< Date object */ + JERRY_OBJECT_TYPE_NUMBER, /**< Number object */ + JERRY_OBJECT_TYPE_REGEXP, /**< RegExp object */ + JERRY_OBJECT_TYPE_STRING, /**< String object */ + JERRY_OBJECT_TYPE_SYMBOL, /**< Symbol object */ + JERRY_OBJECT_TYPE_GENERATOR, /**< Generator object */ + JERRY_OBJECT_TYPE_BIGINT, /**< BigInt object */ + JERRY_OBJECT_TYPE_WEAKREF, /**< WeakRef object */ +} jerry_object_type_t; + +/** + * JerryScript function object type information. + */ +typedef enum +{ + JERRY_FUNCTION_TYPE_NONE = 0u, /**< Non function type */ + JERRY_FUNCTION_TYPE_GENERIC, /**< Generic JavaScript function */ + JERRY_FUNCTION_TYPE_ACCESSOR, /**< Accessor function */ + JERRY_FUNCTION_TYPE_BOUND, /**< Bound function */ + JERRY_FUNCTION_TYPE_ARROW, /**< Arrow function */ + JERRY_FUNCTION_TYPE_GENERATOR, /**< Generator function */ +} jerry_function_type_t; + +/** + * JerryScript iterator object type information. + */ +typedef enum +{ + JERRY_ITERATOR_TYPE_NONE = 0u, /**< Non iterator type */ + JERRY_ITERATOR_TYPE_ARRAY, /**< Array iterator */ + JERRY_ITERATOR_TYPE_STRING, /**< String iterator */ + JERRY_ITERATOR_TYPE_MAP, /**< Map iterator */ + JERRY_ITERATOR_TYPE_SET, /**< Set iterator */ +} jerry_iterator_type_t; + +/** + * Module related types. + */ + +/** + * An enum representing the current status of a module + */ +typedef enum +{ + JERRY_MODULE_STATE_INVALID = 0, /**< return value for jerry_module_state when its argument is not a module */ + JERRY_MODULE_STATE_UNLINKED = 1, /**< module is currently unlinked */ + JERRY_MODULE_STATE_LINKING = 2, /**< module is currently being linked */ + JERRY_MODULE_STATE_LINKED = 3, /**< module has been linked (its dependencies has been resolved) */ + JERRY_MODULE_STATE_EVALUATING = 4, /**< module is currently being evaluated */ + JERRY_MODULE_STATE_EVALUATED = 5, /**< module has been evaluated (its source code has been executed) */ + JERRY_MODULE_STATE_ERROR = 6, /**< an error has been encountered before the evaluated state is reached */ +} jerry_module_state_t; + +/** + * Callback which is called by jerry_module_link to get the referenced module. + */ +typedef jerry_value_t (*jerry_module_resolve_cb_t) (const jerry_value_t specifier, + const jerry_value_t referrer, + void *user_p); + +/** + * Callback which is called when an import is resolved dynamically to get the referenced module. + */ +typedef jerry_value_t (*jerry_module_import_cb_t) (const jerry_value_t specifier, + const jerry_value_t user_value, + void *user_p); + +/** + * Callback which is called after the module enters into linked, evaluated or error state. + */ +typedef void (*jerry_module_state_changed_cb_t) (jerry_module_state_t new_state, + const jerry_value_t module, + const jerry_value_t value, + void *user_p); + +/** + * Callback which is called when an import.meta expression of a module is evaluated the first time. + */ +typedef void (*jerry_module_import_meta_cb_t) (const jerry_value_t module, + const jerry_value_t meta_object, + void *user_p); + +/** + * Callback which is called by jerry_module_evaluate to evaluate the native module. + */ +typedef jerry_value_t (*jerry_native_module_evaluate_cb_t) (const jerry_value_t native_module); + +/** + * Proxy related types. + */ + +/** + * JerryScript special Proxy object options. + */ +typedef enum +{ + JERRY_PROXY_SKIP_RESULT_VALIDATION = (1u << 0), /**< skip result validation for [[GetPrototypeOf]], + * [[SetPrototypeOf]], [[IsExtensible]], + * [[PreventExtensions]], [[GetOwnProperty]], + * [[DefineOwnProperty]], [[HasProperty]], [[Get]], + * [[Set]], [[Delete]] and [[OwnPropertyKeys]] */ +} jerry_proxy_custom_behavior_t; + +/** + * Promise related types. + */ + +/** + * Enum values representing various Promise states. + */ +typedef enum +{ + JERRY_PROMISE_STATE_NONE = 0u, /**< Invalid/Unknown state (possibly called on a non-promise object). */ + JERRY_PROMISE_STATE_PENDING, /**< Promise is in "Pending" state. */ + JERRY_PROMISE_STATE_FULFILLED, /**< Promise is in "Fulfilled" state. */ + JERRY_PROMISE_STATE_REJECTED, /**< Promise is in "Rejected" state. */ +} jerry_promise_state_t; + +/** + * Event types for jerry_promise_event_cb_t callback function. + * The description of the 'object' and 'value' arguments are provided for each type. + */ +typedef enum +{ + JERRY_PROMISE_EVENT_CREATE = 0u, /**< a new Promise object is created + * object: the new Promise object + * value: parent Promise for `then` chains, undefined otherwise */ + JERRY_PROMISE_EVENT_RESOLVE, /**< called when a Promise is about to be resolved + * object: the Promise object + * value: value for resolving */ + JERRY_PROMISE_EVENT_REJECT, /**< called when a Promise is about to be rejected + * object: the Promise object + * value: value for rejecting */ + JERRY_PROMISE_EVENT_RESOLVE_FULFILLED, /**< called when a resolve is called on a fulfilled Promise + * object: the Promise object + * value: value for resolving */ + JERRY_PROMISE_EVENT_REJECT_FULFILLED, /**< called when a reject is called on a fulfilled Promise + * object: the Promise object + * value: value for rejecting */ + JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER, /**< called when a Promise is rejected without a handler + * object: the Promise object + * value: value for rejecting */ + JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED, /**< called when a catch handler is added to a rejected + * Promise which did not have a catch handler before + * object: the Promise object + * value: undefined */ + JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB, /**< called before executing a Promise reaction job + * object: the Promise object + * value: undefined */ + JERRY_PROMISE_EVENT_AFTER_REACTION_JOB, /**< called after a Promise reaction job is completed + * object: the Promise object + * value: undefined */ + JERRY_PROMISE_EVENT_ASYNC_AWAIT, /**< called when an async function awaits the result of a Promise object + * object: internal object representing the execution status + * value: the Promise object */ + JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE, /**< called when an async function is continued with resolve + * object: internal object representing the execution status + * value: value for resolving */ + JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT, /**< called when an async function is continued with reject + * object: internal object representing the execution status + * value: value for rejecting */ + JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE, /**< called when an async function resolve is completed + * object: internal object representing the execution status + * value: value for resolving */ + JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT, /**< called when an async function reject is completed + * object: internal object representing the execution status + * value: value for rejecting */ +} jerry_promise_event_type_t; + +/** + * Filter types for jerry_promise_on_event callback function. + * The callback is only called for those events which are enabled by the filters. + */ +typedef enum +{ + JERRY_PROMISE_EVENT_FILTER_DISABLE = 0, /**< disable reporting of all events */ + JERRY_PROMISE_EVENT_FILTER_CREATE = (1 << 0), /**< enables the following event: + * JERRY_PROMISE_EVENT_CREATE */ + JERRY_PROMISE_EVENT_FILTER_RESOLVE = (1 << 1), /**< enables the following event: + * JERRY_PROMISE_EVENT_RESOLVE */ + JERRY_PROMISE_EVENT_FILTER_REJECT = (1 << 2), /**< enables the following event: + * JERRY_PROMISE_EVENT_REJECT */ + JERRY_PROMISE_EVENT_FILTER_ERROR = (1 << 3), /**< enables the following events: + * JERRY_PROMISE_EVENT_RESOLVE_FULFILLED + * JERRY_PROMISE_EVENT_REJECT_FULFILLED + * JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER + * JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED */ + JERRY_PROMISE_EVENT_FILTER_REACTION_JOB = (1 << 4), /**< enables the following events: + * JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB + * JERRY_PROMISE_EVENT_AFTER_REACTION_JOB */ + JERRY_PROMISE_EVENT_FILTER_ASYNC_MAIN = (1 << 5), /**< enables the following event: + * JERRY_PROMISE_EVENT_ASYNC_AWAIT */ + JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB = (1 << 6), /**< enables the following events: + * JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE + * JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT + * JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE + * JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT */ +} jerry_promise_event_filter_t; + +/** + * Notification callback for tracking Promise and async function operations. + */ +typedef void (*jerry_promise_event_cb_t) (jerry_promise_event_type_t event_type, + const jerry_value_t object, + const jerry_value_t value, + void *user_p); + +/** + * Symbol related types. + */ + +/** + * List of well-known symbols. + */ +typedef enum +{ + JERRY_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well-known symbol */ + JERRY_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well-known symbol */ + JERRY_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well-known symbol */ + JERRY_SYMBOL_ITERATOR, /**< @@iterator well-known symbol */ + JERRY_SYMBOL_MATCH, /**< @@match well-known symbol */ + JERRY_SYMBOL_REPLACE, /**< @@replace well-known symbol */ + JERRY_SYMBOL_SEARCH, /**< @@search well-known symbol */ + JERRY_SYMBOL_SPECIES, /**< @@species well-known symbol */ + JERRY_SYMBOL_SPLIT, /**< @@split well-known symbol */ + JERRY_SYMBOL_TO_PRIMITIVE, /**< @@toPrimitive well-known symbol */ + JERRY_SYMBOL_TO_STRING_TAG, /**< @@toStringTag well-known symbol */ + JERRY_SYMBOL_UNSCOPABLES, /**< @@unscopables well-known symbol */ + JERRY_SYMBOL_MATCH_ALL, /**< @@matchAll well-known symbol */ +} jerry_well_known_symbol_t; + +/** + * TypedArray related types. + */ + +/** + * TypedArray types. + */ +typedef enum +{ + JERRY_TYPEDARRAY_INVALID = 0, + JERRY_TYPEDARRAY_UINT8, + JERRY_TYPEDARRAY_UINT8CLAMPED, + JERRY_TYPEDARRAY_INT8, + JERRY_TYPEDARRAY_UINT16, + JERRY_TYPEDARRAY_INT16, + JERRY_TYPEDARRAY_UINT32, + JERRY_TYPEDARRAY_INT32, + JERRY_TYPEDARRAY_FLOAT32, + JERRY_TYPEDARRAY_FLOAT64, + JERRY_TYPEDARRAY_BIGINT64, + JERRY_TYPEDARRAY_BIGUINT64, +} jerry_typedarray_type_t; + +/** + * Container types. + */ +typedef enum +{ + JERRY_CONTAINER_TYPE_INVALID = 0, /**< Invalid container */ + JERRY_CONTAINER_TYPE_MAP, /**< Map type */ + JERRY_CONTAINER_TYPE_SET, /**< Set type */ + JERRY_CONTAINER_TYPE_WEAKMAP, /**< WeakMap type */ + JERRY_CONTAINER_TYPE_WEAKSET, /**< WeakSet type */ +} jerry_container_type_t; + +/** + * Container operations + */ +typedef enum +{ + JERRY_CONTAINER_OP_ADD, /**< Set/WeakSet add operation */ + JERRY_CONTAINER_OP_GET, /**< Map/WeakMap get operation */ + JERRY_CONTAINER_OP_SET, /**< Map/WeakMap set operation */ + JERRY_CONTAINER_OP_HAS, /**< Set/WeakSet/Map/WeakMap has operation */ + JERRY_CONTAINER_OP_DELETE, /**< Set/WeakSet/Map/WeakMap delete operation */ + JERRY_CONTAINER_OP_SIZE, /**< Set/WeakSet/Map/WeakMap size operation */ + JERRY_CONTAINER_OP_CLEAR, /**< Set/Map clear operation */ +} jerry_container_op_t; + +/** + * Miscellaneous types. + */ + +/** + * Enabled fields of jerry_source_info_t. + */ +typedef enum +{ + JERRY_SOURCE_INFO_HAS_SOURCE_CODE = (1 << 0), /**< source_code field is valid */ + JERRY_SOURCE_INFO_HAS_FUNCTION_ARGUMENTS = (1 << 1), /**< function_arguments field is valid */ + JERRY_SOURCE_INFO_HAS_SOURCE_RANGE = (1 << 2), /**< both source_range_start and source_range_length + * fields are valid */ +} jerry_source_info_enabled_fields_t; + +/** + * Source related information of a script/module/function. + */ +typedef struct +{ + uint32_t enabled_fields; /**< combination of jerry_source_info_enabled_fields_t values */ + jerry_value_t source_code; /**< script source code or function body */ + jerry_value_t function_arguments; /**< function arguments */ + uint32_t source_range_start; /**< start position of the function in the source code */ + uint32_t source_range_length; /**< source length of the function in the source code */ +} jerry_source_info_t; + +/** + * Array buffer types. + */ + +/** + * Type of an array buffer. + */ +typedef enum +{ + JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER, /**< the object is an array buffer object */ + JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER, /**< the object is a shared array buffer object */ +} jerry_arraybuffer_type_t; + +/** + * Callback for allocating the backing store of array buffer or shared array buffer objects. + */ +typedef uint8_t *(*jerry_arraybuffer_allocate_cb_t) (jerry_arraybuffer_type_t buffer_type, + uint32_t buffer_size, + void **arraybuffer_user_p, + void *user_p); + +/** + * Callback for freeing the backing store of array buffer or shared array buffer objects. + */ +typedef void (*jerry_arraybuffer_free_cb_t) (jerry_arraybuffer_type_t buffer_type, + uint8_t *buffer_p, + uint32_t buffer_size, + void *arraybuffer_user_p, + void *user_p); + +/** + * @} + */ + +JERRY_C_API_END + +#endif /* !JERRYSCRIPT_TYPES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript.h b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript.h new file mode 100644 index 00000000..5a38ad0b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/jerryscript.h @@ -0,0 +1,36 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JERRYSCRIPT_H +#define JERRYSCRIPT_H + +/** + * Major version of JerryScript API. + */ +#define JERRY_API_MAJOR_VERSION 3 + +/** + * Minor version of JerryScript API. + */ +#define JERRY_API_MINOR_VERSION 0 + +/** + * Patch version of JerryScript API. + */ +#define JERRY_API_PATCH_VERSION 0 + +#include "jerryscript-core.h" + +#endif /* !JERRYSCRIPT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/include/meson.build b/src/loaders/lottie/jerryscript/jerry-core/include/meson.build new file mode 100644 index 00000000..36caacaa --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/include/meson.build @@ -0,0 +1,13 @@ +source_file = [ + 'jerry-config.h', + 'jerryscript-compiler.h', + 'jerryscript-core.h', + 'jerryscript-port.h', + 'jerryscript-types.h', + 'jerryscript.h' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.cpp b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.cpp new file mode 100644 index 00000000..7a7a4290 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.cpp @@ -0,0 +1,156 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jcontext.h" + +/** \addtogroup context Context + * @{ + */ + +/** + * Check the existence of the ECMA_STATUS_EXCEPTION flag. + * + * @return true - if the flag is set + * false - otherwise + */ +bool +jcontext_has_pending_exception (void) +{ + return JERRY_CONTEXT (status_flags) & ECMA_STATUS_EXCEPTION; +} /* jcontext_has_pending_exception */ + +/** + * Check the existence of the ECMA_STATUS_ABORT flag. + * + * @return true - if the flag is set + * false - otherwise + */ +bool +jcontext_has_pending_abort (void) +{ + return JERRY_CONTEXT (status_flags) & ECMA_STATUS_ABORT; +} /* jcontext_has_pending_abort */ + +/** + * Set the abort flag for the context. + * + * @return void + */ +void +jcontext_set_abort_flag (bool is_abort) /**< true - if the abort flag should be set + * false - if the abort flag should be removed */ +{ + JERRY_ASSERT (jcontext_has_pending_exception ()); + + if (is_abort) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ABORT; + } + else + { + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_ABORT; + } +} /* jcontext_set_abort_flag */ + +/** + * Set the exception flag for the context. + * + * @return void + */ +void +jcontext_set_exception_flag (bool is_exception) /**< true - if the exception flag should be set + * false - if the exception flag should be removed */ +{ + if (is_exception) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION; + } + else + { + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_EXCEPTION; + } +} /* jcontext_set_exception_flag */ + +/** + * Raise exception from the given error value. + * + * @return void + */ +void +jcontext_raise_exception (ecma_value_t error) /**< error to raise */ +{ + JERRY_ASSERT (!jcontext_has_pending_exception ()); + JERRY_ASSERT (!jcontext_has_pending_abort ()); + + JERRY_CONTEXT (error_value) = error; + jcontext_set_exception_flag (true); +} /* jcontext_raise_exception */ + +/** + * Release the current exception/abort of the context. + */ +void +jcontext_release_exception (void) +{ + JERRY_ASSERT (jcontext_has_pending_exception ()); + + ecma_free_value (jcontext_take_exception ()); +} /* jcontext_release_exception */ + +/** + * Take the current exception/abort of context. + * + * @return current exception as an ecma-value + */ +ecma_value_t +jcontext_take_exception (void) +{ + JERRY_ASSERT (jcontext_has_pending_exception ()); + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~(ECMA_STATUS_EXCEPTION +#if JERRY_VM_THROW + | ECMA_STATUS_ERROR_THROWN +#endif /* JERRY_VM_THROW */ + | ECMA_STATUS_ABORT); + return JERRY_CONTEXT (error_value); +} /* jcontext_take_exception */ + +#if !JERRY_EXTERNAL_CONTEXT + +/** + * Global context. + */ +jerry_context_t jerry_global_context; + +#if !JERRY_SYSTEM_ALLOCATOR + +/** + * Check size of heap is corresponding to configuration + */ +JERRY_STATIC_ASSERT ((sizeof (jmem_heap_t) <= JMEM_HEAP_SIZE), + size_of_mem_heap_must_be_less_than_or_equal_to_JMEM_HEAP_SIZE); + +/** + * Global heap. + */ +jmem_heap_t jerry_global_heap JERRY_ATTR_ALIGNED (JMEM_ALIGNMENT) JERRY_ATTR_GLOBAL_HEAP; + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +#endif /* !JERRY_EXTERNAL_CONTEXT */ + +/** + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.h b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.h new file mode 100644 index 00000000..1bf35d56 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jcontext/jcontext.h @@ -0,0 +1,322 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Engine context for JerryScript + */ +#ifndef JCONTEXT_H +#define JCONTEXT_H + +#include "ecma-builtins.h" +#include "ecma-helpers.h" +#include "ecma-jobqueue.h" + +#include "jmem.h" +#include "js-parser-internal.h" +#include "re-bytecode.h" +#include "vm-defines.h" + +/** \addtogroup context Context + * @{ + */ + +/** + * Advanced allocator configurations. + */ +/** + * Maximum global heap size in bytes + */ +#define CONFIG_MEM_HEAP_SIZE (JERRY_GLOBAL_HEAP_SIZE * 1024) + +/** + * Maximum stack usage size in bytes + */ +#define CONFIG_MEM_STACK_LIMIT (JERRY_STACK_LIMIT * 1024) + +/** + * Max heap usage limit + */ +#define CONFIG_MAX_GC_LIMIT 8192 + +/** + * Allowed heap usage limit until next garbage collection + * + * Whenever the total allocated memory size reaches the current heap limit, garbage collection will be triggered + * to try and reduce clutter from unreachable objects. If the allocated memory can't be reduced below the limit, + * then the current limit will be incremented by CONFIG_MEM_HEAP_LIMIT. + */ +#if defined(JERRY_GC_LIMIT) && (JERRY_GC_LIMIT != 0) +#define CONFIG_GC_LIMIT JERRY_GC_LIMIT +#else /* !(defined(JERRY_GC_LIMIT) && (JERRY_GC_LIMIT != 0)) */ +#define CONFIG_GC_LIMIT (JERRY_MIN (CONFIG_MEM_HEAP_SIZE / 32, CONFIG_MAX_GC_LIMIT)) +#endif /* defined(JERRY_GC_LIMIT) && (JERRY_GC_LIMIT != 0) */ + +/** + * Amount of newly allocated objects since the last GC run, represented as a fraction of all allocated objects, + * which when reached will trigger garbage collection to run with a low pressure setting. + * + * The fraction is calculated as: + * 1.0 / CONFIG_ECMA_GC_NEW_OBJECTS_FRACTION + */ +#define CONFIG_ECMA_GC_NEW_OBJECTS_FRACTION (16) + +#if !JERRY_SYSTEM_ALLOCATOR +/** + * Heap structure + * + * Memory blocks returned by the allocator must not start from the + * beginning of the heap area because offset 0 is reserved for + * JMEM_CP_NULL. This special constant is used in several places, + * e.g. it marks the end of the property chain list, so it cannot + * be eliminated from the project. Although the allocator cannot + * use the first 8 bytes of the heap, nothing prevents to use it + * for other purposes. Currently the free region start is stored + * there. + */ +typedef struct jmem_heap_t jmem_heap_t; +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +/** + * User context item + */ +typedef struct jerry_context_data_header +{ + struct jerry_context_data_header *next_p; /**< pointer to next context item */ + const jerry_context_data_manager_t *manager_p; /**< manager responsible for deleting this item */ +} jerry_context_data_header_t; + +#define JERRY_CONTEXT_DATA_HEADER_USER_DATA(item_p) ((uint8_t *) (item_p + 1)) + +/** + * JerryScript context + * + * The purpose of this header is storing + * all global variables for Jerry + */ +struct jerry_context_t +{ + /* The value of external context members must be preserved across initializations and cleanups. */ +#if JERRY_EXTERNAL_CONTEXT +#if !JERRY_SYSTEM_ALLOCATOR + jmem_heap_t *heap_p; /**< point to the heap aligned to JMEM_ALIGNMENT. */ + uint32_t heap_size; /**< size of the heap */ +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +#endif /* JERRY_EXTERNAL_CONTEXT */ + + ecma_global_object_t *global_object_p; /**< current global object */ + jmem_heap_free_t *jmem_heap_list_skip_p; /**< improves deallocation performance */ + jmem_pools_chunk_t *jmem_free_8_byte_chunk_p; /**< list of free eight byte pool chunks */ +#if JERRY_BUILTIN_REGEXP + re_compiled_code_t *re_cache[RE_CACHE_SIZE]; /**< regex cache */ +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_CPOINTER_32_BIT + jmem_pools_chunk_t *jmem_free_16_byte_chunk_p; /**< list of free sixteen byte pool chunks */ +#endif /* JERRY_CPOINTER_32_BIT */ + const lit_utf8_byte_t *const *lit_magic_string_ex_array; /**< array of external magic strings */ + const lit_utf8_size_t *lit_magic_string_ex_sizes; /**< external magic string lengths */ + jmem_cpointer_t ecma_gc_objects_cp; /**< List of currently alive objects. */ + jmem_cpointer_t string_list_first_cp; /**< first item of the literal string list */ + jmem_cpointer_t symbol_list_first_cp; /**< first item of the global symbol list */ + jmem_cpointer_t number_list_first_cp; /**< first item of the literal number list */ +#if JERRY_BUILTIN_BIGINT + jmem_cpointer_t bigint_list_first_cp; /**< first item of the literal bigint list */ +#endif /* JERRY_BUILTIN_BIGINT */ + jmem_cpointer_t global_symbols_cp[ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT]; /**< global symbols */ + +#if JERRY_MODULE_SYSTEM + ecma_module_t *module_current_p; /**< current module context */ + jerry_module_state_changed_cb_t module_state_changed_callback_p; /**< callback which is called after the + * state of a module is changed */ + void *module_state_changed_callback_user_p; /**< user pointer for module_state_changed_callback_p */ + jerry_module_import_meta_cb_t module_import_meta_callback_p; /**< callback which is called when an + * import.meta expression of a module + * is evaluated the first time */ + void *module_import_meta_callback_user_p; /**< user pointer for module_import_meta_callback_p */ + jerry_module_import_cb_t module_import_callback_p; /**< callback for dynamic module import */ + void *module_import_callback_user_p; /**< user pointer for module_import_callback_p */ +#endif /* JERRY_MODULE_SYSTEM */ + + vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */ + jerry_context_data_header_t *context_data_p; /**< linked list of user-provided context-specific pointers */ + jerry_external_string_free_cb_t external_string_free_callback_p; /**< free callback for external strings */ + void *error_object_created_callback_user_p; /**< user pointer for error_object_update_callback_p */ + jerry_error_object_created_cb_t error_object_created_callback_p; /**< decorator callback for Error objects */ + size_t ecma_gc_objects_number; /**< number of currently allocated objects */ + size_t ecma_gc_new_objects; /**< number of newly allocated objects since last GC session */ + size_t jmem_heap_allocated_size; /**< size of allocated regions */ + size_t jmem_heap_limit; /**< current limit of heap usage, that is upon being reached, + * causes call of "try give memory back" callbacks */ + ecma_value_t error_value; /**< currently thrown error value */ + uint32_t lit_magic_string_ex_count; /**< external magic strings count */ + uint32_t jerry_init_flags; /**< run-time configuration flags */ + uint32_t status_flags; /**< run-time flags (the top 8 bits are used for passing class parsing options) */ + +#if (JERRY_GC_MARK_LIMIT != 0) + uint32_t ecma_gc_mark_recursion_limit; /**< GC mark recursion limit */ +#endif /* (JERRY_GC_MARK_LIMIT != 0) */ + +#if JERRY_PROPERTY_HASHMAP + uint8_t ecma_prop_hashmap_alloc_state; /**< property hashmap allocation state: 0-4, + * if !0 property hashmap allocation is disabled */ +#endif /* JERRY_PROPERTY_HASHMAP */ + +#if JERRY_BUILTIN_REGEXP + uint8_t re_cache_idx; /**< evicted item index when regex cache is full (round-robin) */ +#endif /* JERRY_BUILTIN_REGEXP */ + ecma_job_queue_item_t *job_queue_head_p; /**< points to the head item of the job queue */ + ecma_job_queue_item_t *job_queue_tail_p; /**< points to the tail item of the job queue */ +#if JERRY_PROMISE_CALLBACK + uint32_t promise_callback_filters; /**< reported event types for promise callback */ + void *promise_callback_user_p; /**< user pointer for promise callback */ + jerry_promise_event_cb_t promise_callback; /**< user function for tracking Promise object operations */ +#endif /* JERRY_PROMISE_CALLBACK */ + +#if JERRY_BUILTIN_TYPEDARRAY + uint32_t arraybuffer_compact_allocation_limit; /**< maximum size of compact allocation */ + jerry_arraybuffer_allocate_cb_t arraybuffer_allocate_callback; /**< callback for allocating + * arraybuffer memory */ + jerry_arraybuffer_free_cb_t arraybuffer_free_callback; /**< callback for freeing arraybuffer memory */ + void *arraybuffer_allocate_callback_user_p; /**< user pointer passed to arraybuffer_allocate_callback + * and arraybuffer_free_callback functions */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + +#if JERRY_VM_HALT + uint32_t vm_exec_stop_frequency; /**< reset value for vm_exec_stop_counter */ + uint32_t vm_exec_stop_counter; /**< down counter for reducing the calls of vm_exec_stop_cb */ + void *vm_exec_stop_user_p; /**< user pointer for vm_exec_stop_cb */ + ecma_vm_exec_stop_callback_t vm_exec_stop_cb; /**< user function which returns whether the + * ECMAScript execution should be stopped */ +#endif /* JERRY_VM_HALT */ + +#if JERRY_VM_THROW + void *vm_throw_callback_user_p; /**< user pointer for vm_throw_callback_p */ + jerry_throw_cb_t vm_throw_callback_p; /**< callback for capturing throws */ +#endif /* JERRY_VM_THROW */ + +#if (JERRY_STACK_LIMIT != 0) + uintptr_t stack_base; /**< stack base marker */ +#endif /* (JERRY_STACK_LIMIT != 0) */ + + /* This must be at the end of the context for performance reasons */ +#if JERRY_LCACHE + /** hash table for caching the last access of properties */ + ecma_lcache_hash_entry_t lcache[ECMA_LCACHE_HASH_ROWS_COUNT][ECMA_LCACHE_HASH_ROW_LENGTH]; +#endif /* JERRY_LCACHE */ + + /** + * Allowed values and it's meaning: + * * NULL (0x0): the current "new.target" is undefined, that is the execution is inside a normal method. + * * Any other valid function object pointer: the current "new.target" is valid and it is constructor call. + */ + ecma_object_t *current_new_target_p; +}; + +#if JERRY_EXTERNAL_CONTEXT + +/* + * This part is for JerryScript which uses external context. + */ + +#define JERRY_CONTEXT_STRUCT (*jerry_port_context_get ()) +#define JERRY_CONTEXT(field) (jerry_port_context_get ()->field) + +#if !JERRY_SYSTEM_ALLOCATOR + +#define JMEM_HEAP_SIZE (JERRY_CONTEXT (heap_size)) + +#define JMEM_HEAP_AREA_SIZE (JMEM_HEAP_SIZE - JMEM_ALIGNMENT) + +struct jmem_heap_t +{ + jmem_heap_free_t first; /**< first node in free region list */ + uint8_t area[]; /**< heap area */ +}; + +#define JERRY_HEAP_CONTEXT(field) (JERRY_CONTEXT (heap_p)->field) + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +#else /* !JERRY_EXTERNAL_CONTEXT */ + +/* + * This part is for JerryScript which uses default context. + */ + +/** + * Global context. + */ +extern jerry_context_t jerry_global_context; + +/** + * Config-independent name for context. + */ +#define JERRY_CONTEXT_STRUCT (jerry_global_context) + +/** + * Provides a reference to a field in the current context. + */ +#define JERRY_CONTEXT(field) (jerry_global_context.field) + +#if !JERRY_SYSTEM_ALLOCATOR + +/** + * Size of heap + */ +#define JMEM_HEAP_SIZE ((size_t) (CONFIG_MEM_HEAP_SIZE)) + +/** + * Calculate heap area size, leaving space for a pointer to the free list + */ +#define JMEM_HEAP_AREA_SIZE (JMEM_HEAP_SIZE - JMEM_ALIGNMENT) + +struct jmem_heap_t +{ + jmem_heap_free_t first; /**< first node in free region list */ + uint8_t area[JMEM_HEAP_AREA_SIZE]; /**< heap area */ +}; + +/** + * Global heap. + */ +extern jmem_heap_t jerry_global_heap; + +/** + * Provides a reference to a field of the heap. + */ +#define JERRY_HEAP_CONTEXT(field) (jerry_global_heap.field) + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +#endif /* JERRY_EXTERNAL_CONTEXT */ + +void jcontext_set_exception_flag (bool is_exception); + +void jcontext_set_abort_flag (bool is_abort); + +bool jcontext_has_pending_exception (void); + +bool jcontext_has_pending_abort (void); + +void jcontext_raise_exception (ecma_value_t error); + +void jcontext_release_exception (void); + +ecma_value_t jcontext_take_exception (void); + +/** + * @} + */ + +#endif /* !JCONTEXT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jcontext/meson.build b/src/loaders/lottie/jerryscript/jerry-core/jcontext/meson.build new file mode 100644 index 00000000..ca41b816 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jcontext/meson.build @@ -0,0 +1,9 @@ +source_file = [ + 'jcontext.h', + 'jcontext.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator-internal.h b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator-internal.h new file mode 100644 index 00000000..f71d9eac --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator-internal.h @@ -0,0 +1,78 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JMEM_ALLOCATOR_INTERNAL_H +#define JMEM_ALLOCATOR_INTERNAL_H + +#ifndef JMEM_ALLOCATOR_INTERNAL +#error "The header is for internal routines of memory allocator component. Please, don't use the routines directly." +#endif /* !JMEM_ALLOCATOR_INTERNAL */ + +/** \addtogroup mem Memory allocation + * @{ + */ + +/** + * @{ + * Valgrind-related options and headers + */ +#if JERRY_VALGRIND +#include "memcheck.h" + +#define JMEM_VALGRIND_NOACCESS_SPACE(p, s) VALGRIND_MAKE_MEM_NOACCESS ((p), (s)) +#define JMEM_VALGRIND_UNDEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_UNDEFINED ((p), (s)) +#define JMEM_VALGRIND_DEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_DEFINED ((p), (s)) +#define JMEM_VALGRIND_MALLOCLIKE_SPACE(p, s) VALGRIND_MALLOCLIKE_BLOCK ((p), (s), 0, 0) +#define JMEM_VALGRIND_RESIZE_SPACE(p, o, n) VALGRIND_RESIZEINPLACE_BLOCK ((p), (o), (n), 0) +#define JMEM_VALGRIND_FREELIKE_SPACE(p) VALGRIND_FREELIKE_BLOCK ((p), 0) +#else /* !JERRY_VALGRIND */ +#define JMEM_VALGRIND_NOACCESS_SPACE(p, s) +#define JMEM_VALGRIND_UNDEFINED_SPACE(p, s) +#define JMEM_VALGRIND_DEFINED_SPACE(p, s) +#define JMEM_VALGRIND_MALLOCLIKE_SPACE(p, s) +#define JMEM_VALGRIND_RESIZE_SPACE(p, o, n) +#define JMEM_VALGRIND_FREELIKE_SPACE(p) +#endif /* JERRY_VALGRIND */ +/** @} */ + +void jmem_heap_init (void); +void jmem_heap_finalize (void); +bool jmem_is_heap_pointer (const void *pointer); +void *jmem_heap_alloc_block_internal (const size_t size); +void jmem_heap_free_block_internal (void *ptr, const size_t size); + +/** + * \addtogroup poolman Memory pool manager + * @{ + */ + +void jmem_pools_finalize (void); + +/** + * @} + * @} + */ + +/** + * @{ + * Jerry mem-stat definitions + */ +#define JMEM_HEAP_STAT_INIT() +#define JMEM_HEAP_STAT_ALLOC(v1) JERRY_UNUSED (v1) +#define JMEM_HEAP_STAT_FREE(v1) JERRY_UNUSED (v1) + +/** @} */ + +#endif /* !JMEM_ALLOCATOR_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator.cpp b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator.cpp new file mode 100644 index 00000000..d56f5a36 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-allocator.cpp @@ -0,0 +1,107 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Allocator implementation + */ +#include "ecma-globals.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" + +#define JMEM_ALLOCATOR_INTERNAL +#include "jmem-allocator-internal.h" + +/** + * Initialize memory allocators. + */ +void +jmem_init (void) +{ + jmem_heap_init (); +} /* jmem_init */ + +/** + * Finalize memory allocators. + */ +void +jmem_finalize (void) +{ + jmem_pools_finalize (); + jmem_heap_finalize (); +} /* jmem_finalize */ + +/** + * Compress pointer + * + * @return packed pointer + */ +jmem_cpointer_t JERRY_ATTR_PURE +jmem_compress_pointer (const void *pointer_p) /**< pointer to compress */ +{ + JERRY_ASSERT (pointer_p != NULL); + JERRY_ASSERT (jmem_is_heap_pointer (pointer_p)); + + uintptr_t uint_ptr = (uintptr_t) pointer_p; + + JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0); + +#if defined(ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY) && JERRY_CPOINTER_32_BIT + JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr); +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY || !JERRY_CPOINTER_32_BIT */ + const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first); + + uint_ptr -= heap_start; + uint_ptr >>= JMEM_ALIGNMENT_LOG; + +#if JERRY_CPOINTER_32_BIT + JERRY_ASSERT (uint_ptr <= UINT32_MAX); +#else /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (uint_ptr <= UINT16_MAX); +#endif /* JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (uint_ptr != JMEM_CP_NULL); +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY && JERRY_CPOINTER_32_BIT */ + + return (jmem_cpointer_t) uint_ptr; +} /* jmem_compress_pointer */ + +/** + * Decompress pointer + * + * @return unpacked pointer + */ +void *JERRY_ATTR_PURE +jmem_decompress_pointer (uintptr_t compressed_pointer) /**< pointer to decompress */ +{ + JERRY_ASSERT (compressed_pointer != JMEM_CP_NULL); + + uintptr_t uint_ptr = compressed_pointer; + + JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr); + +#if defined(ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY) && JERRY_CPOINTER_32_BIT + JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0); +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY || !JERRY_CPOINTER_32_BIT */ + const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first); + + uint_ptr <<= JMEM_ALIGNMENT_LOG; + uint_ptr += heap_start; + + JERRY_ASSERT (jmem_is_heap_pointer ((void *) uint_ptr)); +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY && JERRY_CPOINTER_32_BIT */ + + return (void *) uint_ptr; +} /* jmem_decompress_pointer */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-heap.cpp b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-heap.cpp new file mode 100644 index 00000000..1d3b1f4f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-heap.cpp @@ -0,0 +1,731 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Heap implementation + */ + +#include "ecma-gc.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-bit-fields.h" +#include "jrt-libc-includes.h" + +#define JMEM_ALLOCATOR_INTERNAL +#include "jmem-allocator-internal.h" + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup heap Heap + * @{ + */ + +#if !JERRY_SYSTEM_ALLOCATOR +/** + * End of list marker. + */ +#define JMEM_HEAP_END_OF_LIST ((uint32_t) 0xffffffff) + +/** + * @{ + */ +#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY +/* In this case we simply store the pointer, since it fits anyway. */ +#define JMEM_HEAP_GET_OFFSET_FROM_ADDR(p) ((uint32_t) (p)) +#define JMEM_HEAP_GET_ADDR_FROM_OFFSET(u) ((jmem_heap_free_t *) (u)) +#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +/** + * Get heap offset from address + */ +#define JMEM_HEAP_GET_OFFSET_FROM_ADDR(p) ((uint32_t) ((uint8_t *) (p) -JERRY_HEAP_CONTEXT (area))) + +/** + * Get heap address from offset + */ +#define JMEM_HEAP_GET_ADDR_FROM_OFFSET(u) ((jmem_heap_free_t *) (JERRY_HEAP_CONTEXT (area) + (u))) +#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ +/** + * @} + */ + +/** + * Get end of region + * + * @return pointer to the end of the region + */ +static inline jmem_heap_free_t * JERRY_ATTR_PURE +jmem_heap_get_region_end (jmem_heap_free_t *curr_p) /**< current region */ +{ + return (jmem_heap_free_t *) ((uint8_t *) curr_p + curr_p->size); +} /* jmem_heap_get_region_end */ +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +/** + * Startup initialization of heap + */ +void +jmem_heap_init (void) +{ +#if !JERRY_SYSTEM_ALLOCATOR +#if !JERRY_CPOINTER_32_BIT + /* the maximum heap size for 16bit compressed pointers should be 512K */ + JERRY_ASSERT (((UINT16_MAX + 1) << JMEM_ALIGNMENT_LOG) >= JMEM_HEAP_SIZE); +#endif /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT ((uintptr_t) JERRY_HEAP_CONTEXT (area) % JMEM_ALIGNMENT == 0); + + JERRY_CONTEXT (jmem_heap_limit) = CONFIG_GC_LIMIT; + + jmem_heap_free_t *const region_p = (jmem_heap_free_t *) JERRY_HEAP_CONTEXT (area); + + region_p->size = JMEM_HEAP_AREA_SIZE; + region_p->next_offset = JMEM_HEAP_END_OF_LIST; + + JERRY_HEAP_CONTEXT (first).size = 0; + JERRY_HEAP_CONTEXT (first).next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (region_p); + + JERRY_CONTEXT (jmem_heap_list_skip_p) = &JERRY_HEAP_CONTEXT (first); + + JMEM_VALGRIND_NOACCESS_SPACE (&JERRY_HEAP_CONTEXT (first), sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (JERRY_HEAP_CONTEXT (area), JMEM_HEAP_AREA_SIZE); + +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + JMEM_HEAP_STAT_INIT (); +} /* jmem_heap_init */ + +/** + * Finalize heap + */ +void +jmem_heap_finalize (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_allocated_size) == 0); +#if !JERRY_SYSTEM_ALLOCATOR + JMEM_VALGRIND_NOACCESS_SPACE (&JERRY_HEAP_CONTEXT (first), JMEM_HEAP_SIZE); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_heap_finalize */ + +/** + * Allocation of memory region. + * + * See also: + * jmem_heap_alloc_block + * + * @return pointer to allocated memory block - if allocation is successful, + * NULL - if there is not enough memory. + */ +static void *JERRY_ATTR_HOT +jmem_heap_alloc (const size_t size) /**< size of requested block */ +{ +#if !JERRY_SYSTEM_ALLOCATOR + /* Align size. */ + const size_t required_size = ((size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT) * JMEM_ALIGNMENT; + jmem_heap_free_t *data_space_p = NULL; + + JMEM_VALGRIND_DEFINED_SPACE (&JERRY_HEAP_CONTEXT (first), sizeof (jmem_heap_free_t)); + + /* Fast path for 8 byte chunks, first region is guaranteed to be sufficient. */ + if (required_size == JMEM_ALIGNMENT && JERRY_LIKELY (JERRY_HEAP_CONTEXT (first).next_offset != JMEM_HEAP_END_OF_LIST)) + { + data_space_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (JERRY_HEAP_CONTEXT (first).next_offset); + JERRY_ASSERT (jmem_is_heap_pointer (data_space_p)); + + JMEM_VALGRIND_DEFINED_SPACE (data_space_p, sizeof (jmem_heap_free_t)); + JERRY_CONTEXT (jmem_heap_allocated_size) += JMEM_ALIGNMENT; + + if (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + if (data_space_p->size == JMEM_ALIGNMENT) + { + JERRY_HEAP_CONTEXT (first).next_offset = data_space_p->next_offset; + } + else + { + JERRY_ASSERT (data_space_p->size > JMEM_ALIGNMENT); + + jmem_heap_free_t *remaining_p; + remaining_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (JERRY_HEAP_CONTEXT (first).next_offset) + 1; + + JMEM_VALGRIND_DEFINED_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + remaining_p->size = data_space_p->size - JMEM_ALIGNMENT; + remaining_p->next_offset = data_space_p->next_offset; + JMEM_VALGRIND_NOACCESS_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + + JERRY_HEAP_CONTEXT (first).next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (remaining_p); + } + + JMEM_VALGRIND_NOACCESS_SPACE (data_space_p, sizeof (jmem_heap_free_t)); + + if (JERRY_UNLIKELY (data_space_p == JERRY_CONTEXT (jmem_heap_list_skip_p))) + { + JERRY_CONTEXT (jmem_heap_list_skip_p) = JMEM_HEAP_GET_ADDR_FROM_OFFSET (JERRY_HEAP_CONTEXT (first).next_offset); + } + } + /* Slow path for larger regions. */ + else + { + uint32_t current_offset = JERRY_HEAP_CONTEXT (first).next_offset; + jmem_heap_free_t *prev_p = &JERRY_HEAP_CONTEXT (first); + + while (JERRY_LIKELY (current_offset != JMEM_HEAP_END_OF_LIST)) + { + jmem_heap_free_t *current_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (current_offset); + JERRY_ASSERT (jmem_is_heap_pointer (current_p)); + JMEM_VALGRIND_DEFINED_SPACE (current_p, sizeof (jmem_heap_free_t)); + + const uint32_t next_offset = current_p->next_offset; + JERRY_ASSERT (next_offset == JMEM_HEAP_END_OF_LIST + || jmem_is_heap_pointer (JMEM_HEAP_GET_ADDR_FROM_OFFSET (next_offset))); + + if (current_p->size >= required_size) + { + /* Region is sufficiently big, store address. */ + data_space_p = current_p; + + /* Region was larger than necessary. */ + if (current_p->size > required_size) + { + /* Get address of remaining space. */ + jmem_heap_free_t *const remaining_p = (jmem_heap_free_t *) ((uint8_t *) current_p + required_size); + + /* Update metadata. */ + JMEM_VALGRIND_DEFINED_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + remaining_p->size = current_p->size - (uint32_t) required_size; + remaining_p->next_offset = next_offset; + JMEM_VALGRIND_NOACCESS_SPACE (remaining_p, sizeof (jmem_heap_free_t)); + + /* Update list. */ + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (remaining_p); + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + /* Block is an exact fit. */ + else + { + /* Remove the region from the list. */ + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = next_offset; + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + + JERRY_CONTEXT (jmem_heap_list_skip_p) = prev_p; + + /* Found enough space. */ + JERRY_CONTEXT (jmem_heap_allocated_size) += required_size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + break; + } + + JMEM_VALGRIND_NOACCESS_SPACE (current_p, sizeof (jmem_heap_free_t)); + /* Next in list. */ + prev_p = current_p; + current_offset = next_offset; + } + } + + JMEM_VALGRIND_NOACCESS_SPACE (&JERRY_HEAP_CONTEXT (first), sizeof (jmem_heap_free_t)); + + JERRY_ASSERT ((uintptr_t) data_space_p % JMEM_ALIGNMENT == 0); + JMEM_VALGRIND_MALLOCLIKE_SPACE (data_space_p, size); + + return (void *) data_space_p; +#else /* JERRY_SYSTEM_ALLOCATOR */ + JERRY_CONTEXT (jmem_heap_allocated_size) += size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + return malloc (size); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_heap_alloc */ + +/** + * Allocation of memory block, reclaiming memory if the request cannot be fulfilled. + * + * Note: + * Each failed allocation attempt tries to reclaim memory with an increasing pressure, + * up to 'max_pressure', or until a sufficient memory block is found. When JMEM_PRESSURE_FULL + * is reached, the engine is terminated with JERRY_FATAL_OUT_OF_MEMORY. The `max_pressure` argument + * can be used to limit the maximum pressure, and prevent the engine from terminating. + * + * @return NULL, if the required memory size is 0 or not enough memory + * pointer to the allocated memory block, if allocation is successful + */ +static void * +jmem_heap_gc_and_alloc_block (const size_t size, /**< required memory size */ + jmem_pressure_t max_pressure) /**< pressure limit */ +{ + if (JERRY_UNLIKELY (size == 0)) + { + return NULL; + } + + jmem_pressure_t pressure = JMEM_PRESSURE_NONE; + +#if !JERRY_MEM_GC_BEFORE_EACH_ALLOC + if (JERRY_CONTEXT (jmem_heap_allocated_size) + size >= JERRY_CONTEXT (jmem_heap_limit)) + { + pressure = JMEM_PRESSURE_LOW; + ecma_free_unused_memory (pressure); + } +#else /* !JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + + void *data_space_p = jmem_heap_alloc (size); + + while (JERRY_UNLIKELY (data_space_p == NULL) && JERRY_LIKELY (pressure < max_pressure)) + { + auto v = (int)(pressure); + pressure = (jmem_pressure_t)(++v); + ecma_free_unused_memory (pressure); + data_space_p = jmem_heap_alloc (size); + } + + return data_space_p; +} /* jmem_heap_gc_and_alloc_block */ + +/** + * Internal method for allocating a memory block. + * + * @return NULL, if the required memory size is 0 or not enough memory, or + * pointer to the allocated memory block, if allocation is successful + */ +void *JERRY_ATTR_HOT +jmem_heap_alloc_block_internal (const size_t size) /**< required memory size */ +{ + return jmem_heap_gc_and_alloc_block (size, JMEM_PRESSURE_FULL); +} /* jmem_heap_alloc_block_internal */ + +/** + * Allocation of memory block, reclaiming unused memory if there is not enough. + * + * Note: + * If a sufficiently sized block can't be found, the engine will be terminated with JERRY_FATAL_OUT_OF_MEMORY. + * + * @return NULL, if the required memory is 0 + * pointer to allocated memory block, otherwise + */ +void *JERRY_ATTR_HOT +jmem_heap_alloc_block (const size_t size) /**< required memory size */ +{ + void *block_p = jmem_heap_gc_and_alloc_block (size, JMEM_PRESSURE_FULL); + JMEM_HEAP_STAT_ALLOC (size); + return block_p; +} /* jmem_heap_alloc_block */ + +/** + * Allocation of memory block, reclaiming unused memory if there is not enough. + * + * Note: + * If a sufficiently sized block can't be found, NULL will be returned. + * + * @return NULL, if the required memory size is 0 + * also NULL, if the allocation has failed + * pointer to the allocated memory block, otherwise + */ +void *JERRY_ATTR_HOT +jmem_heap_alloc_block_null_on_error (const size_t size) /**< required memory size */ +{ + void *block_p = jmem_heap_gc_and_alloc_block (size, JMEM_PRESSURE_HIGH); + + return block_p; +} /* jmem_heap_alloc_block_null_on_error */ + +#if !JERRY_SYSTEM_ALLOCATOR +/** + * Finds the block in the free block list which preceeds the argument block + * + * @return pointer to the preceeding block + */ +static jmem_heap_free_t * +jmem_heap_find_prev (const jmem_heap_free_t *const block_p) /**< which memory block's predecessor we're looking for */ +{ + const jmem_heap_free_t *prev_p; + + if (block_p > JERRY_CONTEXT (jmem_heap_list_skip_p)) + { + prev_p = JERRY_CONTEXT (jmem_heap_list_skip_p); + } + else + { + prev_p = &JERRY_HEAP_CONTEXT (first); + } + + JERRY_ASSERT (jmem_is_heap_pointer (block_p)); + const uint32_t block_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (block_p); + + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + /* Find position of region in the list. */ + while (prev_p->next_offset < block_offset) + { + const jmem_heap_free_t *const next_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + JERRY_ASSERT (jmem_is_heap_pointer (next_p)); + + JMEM_VALGRIND_DEFINED_SPACE (next_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p = next_p; + } + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + return (jmem_heap_free_t *) prev_p; +} /* jmem_heap_find_prev */ + +/** + * Inserts the block into the free chain after a specified block. + * + * Note: + * 'jmem_heap_find_prev' can and should be used to find the previous free block + */ +static void +jmem_heap_insert_block (jmem_heap_free_t *block_p, /**< block to insert */ + jmem_heap_free_t *prev_p, /**< the free block after which to insert 'block_p' */ + const size_t size) /**< size of the inserted block */ +{ + JERRY_ASSERT ((uintptr_t) block_p % JMEM_ALIGNMENT == 0); + JERRY_ASSERT (size % JMEM_ALIGNMENT == 0); + + JMEM_VALGRIND_NOACCESS_SPACE (block_p, size); + + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + jmem_heap_free_t *next_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + JMEM_VALGRIND_DEFINED_SPACE (block_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_DEFINED_SPACE (next_p, sizeof (jmem_heap_free_t)); + + const uint32_t block_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (block_p); + + /* Update prev. */ + if (jmem_heap_get_region_end (prev_p) == block_p) + { + /* Can be merged. */ + prev_p->size += (uint32_t) size; + JMEM_VALGRIND_NOACCESS_SPACE (block_p, sizeof (jmem_heap_free_t)); + block_p = prev_p; + } + else + { + block_p->size = (uint32_t) size; + prev_p->next_offset = block_offset; + } + + /* Update next. */ + if (jmem_heap_get_region_end (block_p) == next_p) + { + /* Can be merged. */ + block_p->size += next_p->size; + block_p->next_offset = next_p->next_offset; + } + else + { + block_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (next_p); + } + + JERRY_CONTEXT (jmem_heap_list_skip_p) = prev_p; + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (block_p, sizeof (jmem_heap_free_t)); + JMEM_VALGRIND_NOACCESS_SPACE (next_p, sizeof (jmem_heap_free_t)); +} /* jmem_heap_insert_block */ +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + +/** + * Internal method for freeing a memory block. + * + * @return void + */ +void JERRY_ATTR_HOT +jmem_heap_free_block_internal (void *ptr, /**< pointer to beginning of data space of the block */ + const size_t size /**< size of allocated region */) +{ + JERRY_ASSERT (size > 0); + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_limit) >= JERRY_CONTEXT (jmem_heap_allocated_size)); + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_allocated_size) > 0); + +#if !JERRY_SYSTEM_ALLOCATOR + /* checking that ptr points to the heap */ + JERRY_ASSERT (jmem_is_heap_pointer (ptr)); + JERRY_ASSERT ((uintptr_t) ptr % JMEM_ALIGNMENT == 0); + + const size_t aligned_size = (size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT * JMEM_ALIGNMENT; + + jmem_heap_free_t *const block_p = (jmem_heap_free_t *) ptr; + jmem_heap_free_t *const prev_p = jmem_heap_find_prev (block_p); + jmem_heap_insert_block (block_p, prev_p, aligned_size); + + JERRY_CONTEXT (jmem_heap_allocated_size) -= aligned_size; + + JMEM_VALGRIND_FREELIKE_SPACE (ptr); +#else /* JERRY_SYSTEM_ALLOCATOR */ + JERRY_CONTEXT (jmem_heap_allocated_size) -= size; + free (ptr); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ + while (JERRY_CONTEXT (jmem_heap_allocated_size) + CONFIG_GC_LIMIT <= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) -= CONFIG_GC_LIMIT; + } + + JERRY_ASSERT (JERRY_CONTEXT (jmem_heap_limit) >= JERRY_CONTEXT (jmem_heap_allocated_size)); +} /* jmem_heap_free_block_internal */ + +/** + * Reallocates the memory region pointed to by 'ptr', changing the size of the allocated region. + * + * @return pointer to the reallocated region + */ +void *JERRY_ATTR_HOT +jmem_heap_realloc_block (void *ptr, /**< memory region to reallocate */ + const size_t old_size, /**< current size of the region */ + const size_t new_size) /**< desired new size */ +{ +#if !JERRY_SYSTEM_ALLOCATOR + JERRY_ASSERT (jmem_is_heap_pointer (ptr)); + JERRY_ASSERT ((uintptr_t) ptr % JMEM_ALIGNMENT == 0); + JERRY_ASSERT (old_size != 0); + JERRY_ASSERT (new_size != 0); + + jmem_heap_free_t *const block_p = (jmem_heap_free_t *) ptr; + const size_t aligned_new_size = (new_size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT * JMEM_ALIGNMENT; + const size_t aligned_old_size = (old_size + JMEM_ALIGNMENT - 1) / JMEM_ALIGNMENT * JMEM_ALIGNMENT; + + if (aligned_old_size == aligned_new_size) + { + JMEM_VALGRIND_RESIZE_SPACE (block_p, old_size, new_size); + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + return block_p; + } + + if (aligned_new_size < aligned_old_size) + { + JMEM_VALGRIND_RESIZE_SPACE (block_p, old_size, new_size); + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + jmem_heap_insert_block ((jmem_heap_free_t *) ((uint8_t *) block_p + aligned_new_size), + jmem_heap_find_prev (block_p), + aligned_old_size - aligned_new_size); + + JERRY_CONTEXT (jmem_heap_allocated_size) -= (aligned_old_size - aligned_new_size); + while (JERRY_CONTEXT (jmem_heap_allocated_size) + CONFIG_GC_LIMIT <= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) -= CONFIG_GC_LIMIT; + } + + return block_p; + } + + void *ret_block_p = NULL; + const size_t required_size = aligned_new_size - aligned_old_size; + +#if !JERRY_MEM_GC_BEFORE_EACH_ALLOC + if (JERRY_CONTEXT (jmem_heap_allocated_size) + required_size >= JERRY_CONTEXT (jmem_heap_limit)) + { + ecma_free_unused_memory (JMEM_PRESSURE_LOW); + } +#else /* !JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + + jmem_heap_free_t *prev_p = jmem_heap_find_prev (block_p); + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + jmem_heap_free_t *const next_p = JMEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + + /* Check if block can be extended at the end */ + if (((jmem_heap_free_t *) ((uint8_t *) block_p + aligned_old_size)) == next_p) + { + JMEM_VALGRIND_DEFINED_SPACE (next_p, sizeof (jmem_heap_free_t)); + + if (required_size <= next_p->size) + { + /* Block can be extended, update the list. */ + if (required_size == next_p->size) + { + prev_p->next_offset = next_p->next_offset; + } + else + { + jmem_heap_free_t *const new_next_p = (jmem_heap_free_t *) ((uint8_t *) next_p + required_size); + JMEM_VALGRIND_DEFINED_SPACE (new_next_p, sizeof (jmem_heap_free_t)); + new_next_p->next_offset = next_p->next_offset; + new_next_p->size = (uint32_t) (next_p->size - required_size); + JMEM_VALGRIND_NOACCESS_SPACE (new_next_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (new_next_p); + } + + /* next_p will be marked as undefined space. */ + JMEM_VALGRIND_RESIZE_SPACE (block_p, old_size, new_size); + ret_block_p = block_p; + } + else + { + JMEM_VALGRIND_NOACCESS_SPACE (next_p, sizeof (jmem_heap_free_t)); + } + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + /* + * Check if block can be extended at the front. + * This is less optimal because we need to copy the data, but still better than allocting a new block. + */ + else if (jmem_heap_get_region_end (prev_p) == block_p) + { + if (required_size <= prev_p->size) + { + if (required_size == prev_p->size) + { + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p = jmem_heap_find_prev (prev_p); + JMEM_VALGRIND_DEFINED_SPACE (prev_p, sizeof (jmem_heap_free_t)); + prev_p->next_offset = JMEM_HEAP_GET_OFFSET_FROM_ADDR (next_p); + } + else + { + prev_p->size = (uint32_t) (prev_p->size - required_size); + } + + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + + ret_block_p = (uint8_t *) block_p - required_size; + + /* Mark the the new block as undefined so that we are able to write to it. */ + JMEM_VALGRIND_UNDEFINED_SPACE (ret_block_p, old_size); + /* The blocks are likely to overlap, so mark the old block as defined memory again. */ + JMEM_VALGRIND_DEFINED_SPACE (block_p, old_size); + memmove (ret_block_p, block_p, old_size); + + JMEM_VALGRIND_FREELIKE_SPACE (block_p); + JMEM_VALGRIND_MALLOCLIKE_SPACE (ret_block_p, new_size); + JMEM_VALGRIND_DEFINED_SPACE (ret_block_p, old_size); + } + else + { + JMEM_VALGRIND_NOACCESS_SPACE (prev_p, sizeof (jmem_heap_free_t)); + } + } + + if (ret_block_p != NULL) + { + /* Managed to extend the block. Update memory usage and the skip pointer. */ + JERRY_CONTEXT (jmem_heap_list_skip_p) = prev_p; + JERRY_CONTEXT (jmem_heap_allocated_size) += required_size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + } + else + { + /* Could not extend block. Allocate new region and copy the data. */ + /* jmem_heap_alloc_block_internal will adjust the allocated_size, but insert_block will not, + so we reduce it here first, so that the limit calculation remains consistent. */ + JERRY_CONTEXT (jmem_heap_allocated_size) -= aligned_old_size; + ret_block_p = jmem_heap_alloc_block_internal (new_size); + + /* jmem_heap_alloc_block_internal may trigger garbage collection, which can create new free blocks + * in the heap structure, so we need to look up the previous block again. */ + prev_p = jmem_heap_find_prev (block_p); + + memcpy (ret_block_p, block_p, old_size); + jmem_heap_insert_block (block_p, prev_p, aligned_old_size); + /* jmem_heap_alloc_block_internal will call JMEM_VALGRIND_MALLOCLIKE_SPACE */ + JMEM_VALGRIND_FREELIKE_SPACE (block_p); + } + + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + return ret_block_p; +#else /* JERRY_SYSTEM_ALLOCATOR */ + const size_t required_size = new_size - old_size; + +#if !JERRY_MEM_GC_BEFORE_EACH_ALLOC + if (JERRY_CONTEXT (jmem_heap_allocated_size) + required_size >= JERRY_CONTEXT (jmem_heap_limit)) + { + ecma_free_unused_memory (JMEM_PRESSURE_LOW); + } +#else /* !JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + + JERRY_CONTEXT (jmem_heap_allocated_size) += required_size; + + while (JERRY_CONTEXT (jmem_heap_allocated_size) >= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) += CONFIG_GC_LIMIT; + } + + while (JERRY_CONTEXT (jmem_heap_allocated_size) + CONFIG_GC_LIMIT <= JERRY_CONTEXT (jmem_heap_limit)) + { + JERRY_CONTEXT (jmem_heap_limit) -= CONFIG_GC_LIMIT; + } + + JMEM_HEAP_STAT_FREE (old_size); + JMEM_HEAP_STAT_ALLOC (new_size); + return realloc (ptr, new_size); +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_heap_realloc_block */ + +/** + * Free memory block + * + * @return void + */ +void JERRY_ATTR_HOT +jmem_heap_free_block (void *ptr, /**< pointer to beginning of data space of the block */ + const size_t size) /**< size of allocated region */ +{ + jmem_heap_free_block_internal (ptr, size); + JMEM_HEAP_STAT_FREE (size); + return; +} /* jmem_heap_free_block */ + +#ifndef JERRY_NDEBUG +/** + * Check whether the pointer points to the heap + * + * Note: + * the routine should be used only for assertion checks + * + * @return true - if pointer points to the heap, + * false - otherwise + */ +bool +jmem_is_heap_pointer (const void *pointer) /**< pointer */ +{ +#if !JERRY_SYSTEM_ALLOCATOR + return ((uint8_t *) pointer >= JERRY_HEAP_CONTEXT (area) + && (uint8_t *) pointer <= (JERRY_HEAP_CONTEXT (area) + JMEM_HEAP_AREA_SIZE)); +#else /* JERRY_SYSTEM_ALLOCATOR */ + JERRY_UNUSED (pointer); + return true; +#endif /* !JERRY_SYSTEM_ALLOCATOR */ +} /* jmem_is_heap_pointer */ +#endif /* !JERRY_NDEBUG */ + + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-poolman.cpp b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-poolman.cpp new file mode 100644 index 00000000..c45c774a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem-poolman.cpp @@ -0,0 +1,193 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Memory pool manager implementation + */ + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" + +#define JMEM_ALLOCATOR_INTERNAL +#include "jmem-allocator-internal.h" + +#if JERRY_MEM_GC_BEFORE_EACH_ALLOC +#include "ecma-gc.h" +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup poolman Memory pool manager + * @{ + */ + +/** + * Finalize pool manager + */ +void +jmem_pools_finalize (void) +{ + jmem_pools_collect_empty (); + + JERRY_ASSERT (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) == NULL); +#if JERRY_CPOINTER_32_BIT + JERRY_ASSERT (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) == NULL); +#endif /* JERRY_CPOINTER_32_BIT */ +} /* jmem_pools_finalize */ + +/** + * Allocate a chunk of specified size + * + * @return pointer to allocated chunk, if allocation was successful, + * or NULL - if not enough memory. + */ +void *JERRY_ATTR_HOT +jmem_pools_alloc (size_t size) /**< size of the chunk */ +{ +#if JERRY_MEM_GC_BEFORE_EACH_ALLOC + ecma_gc_run (); +#endif /* JERRY_MEM_GC_BEFORE_EACH_ALLOC */ + +#if JERRY_CPOINTER_32_BIT + if (size <= 8) + { +#else /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (size <= 8); +#endif /* JERRY_CPOINTER_32_BIT */ + + if (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) != NULL) + { + const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); + + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_p->next_p; + JMEM_VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + JMEM_HEAP_STAT_ALLOC (8); + return (void *) chunk_p; + } + else + { + void *chunk_p = jmem_heap_alloc_block_internal (8); + JMEM_HEAP_STAT_ALLOC (8); + return chunk_p; + } + +#if JERRY_CPOINTER_32_BIT + } + + JERRY_ASSERT (size <= 16); + + if (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) != NULL) + { + const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); + + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_p->next_p; + JMEM_VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + JMEM_HEAP_STAT_ALLOC (16); + return (void *) chunk_p; + } + else + { + void *chunk_p = jmem_heap_alloc_block_internal (16); + JMEM_HEAP_STAT_ALLOC (16); + return chunk_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ +} /* jmem_pools_alloc */ + +/** + * Free the chunk + * + * @return void + */ +void JERRY_ATTR_HOT +jmem_pools_free (void *chunk_p, /**< pointer to the chunk */ + size_t size) /**< size of the chunk */ +{ + JERRY_ASSERT (chunk_p != NULL); + JMEM_HEAP_STAT_FREE (size); + + jmem_pools_chunk_t *const chunk_to_free_p = (jmem_pools_chunk_t *) chunk_p; + + JMEM_VALGRIND_DEFINED_SPACE (chunk_to_free_p, size); + +#if JERRY_CPOINTER_32_BIT + if (size <= 8) + { +#else /* !JERRY_CPOINTER_32_BIT */ + JERRY_ASSERT (size <= 8); +#endif /* JERRY_CPOINTER_32_BIT */ + + chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); + JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_to_free_p; + +#if JERRY_CPOINTER_32_BIT + } + else + { + JERRY_ASSERT (size <= 16); + + chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); + JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_to_free_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ + + JMEM_VALGRIND_NOACCESS_SPACE (chunk_to_free_p, size); +} /* jmem_pools_free */ + +/** + * Collect empty pool chunks + */ +void +jmem_pools_collect_empty (void) +{ + jmem_pools_chunk_t *chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); + JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = NULL; + + while (chunk_p) + { + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + jmem_pools_chunk_t *const next_p = chunk_p->next_p; + JMEM_VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + jmem_heap_free_block_internal (chunk_p, 8); + chunk_p = next_p; + } + +#if JERRY_CPOINTER_32_BIT + chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); + JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = NULL; + + while (chunk_p) + { + JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + jmem_pools_chunk_t *const next_p = chunk_p->next_p; + JMEM_VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); + + jmem_heap_free_block_internal (chunk_p, 16); + chunk_p = next_p; + } +#endif /* JERRY_CPOINTER_32_BIT */ +} /* jmem_pools_collect_empty */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem.h b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem.h new file mode 100644 index 00000000..e7b7c180 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/jmem.h @@ -0,0 +1,282 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JMEM_H +#define JMEM_H + +#include "jrt.h" + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup heap Heap + * @{ + */ + +/** + * Logarithm of required alignment for allocated units/blocks + */ +#define JMEM_ALIGNMENT_LOG 3 + +/** + * Representation of NULL value for compressed pointers + */ +#define JMEM_CP_NULL ((jmem_cpointer_t) 0) + +/** + * Required alignment for allocated units/blocks + */ +#define JMEM_ALIGNMENT (1u << JMEM_ALIGNMENT_LOG) + +/** + * Pointer value can be directly stored without compression + */ +#if UINTPTR_MAX <= UINT32_MAX +#define JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY +#endif /* UINTPTR_MAX <= UINT32_MAX */ + +/** + * Mask for tag part in jmem_cpointer_tag_t + */ +#define JMEM_TAG_MASK 0x7u + +/** + * Shift for tag part in jmem_cpointer_tag_t + */ +#if defined(JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY) && JERRY_CPOINTER_32_BIT +#define JMEM_TAG_SHIFT 0 +#else /* !JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY || !JERRY_CPOINTER_32_BIT */ +#define JMEM_TAG_SHIFT 3 +#endif /* JMEM_CAN_STORE_POINTER_VALUE_DIRECTLY && JERRY_CPOINTER_32_BIT */ + +/** + * Bit mask for tag part in jmem_cpointer_tag_t + */ +enum +{ + JMEM_FIRST_TAG_BIT_MASK = (1u << 0), /**< first tag bit mask **/ + JMEM_SECOND_TAG_BIT_MASK = (1u << 1), /**< second tag bit mask **/ + JMEM_THIRD_TAG_BIT_MASK = (1u << 2), /**< third tag bit mask **/ +}; + +/** + * Compressed pointer representations + * + * 16 bit representation: + * The jmem_cpointer_t is defined as uint16_t + * and it can contain any sixteen bit value. + * + * 32 bit representation: + * The jmem_cpointer_t is defined as uint32_t. + * The lower JMEM_ALIGNMENT_LOG bits must be zero. + * The other bits can have any value. + * + * The 16 bit representation always encodes an offset from + * a heap base. The 32 bit representation currently encodes + * raw 32 bit JMEM_ALIGNMENT aligned pointers on 32 bit systems. + * This can be extended to encode a 32 bit offset from a heap + * base on 64 bit systems in the future. There are no plans + * to support more than 4G address space for JerryScript. + */ + +/** + * Compressed pointer + */ +#if JERRY_CPOINTER_32_BIT +typedef uint32_t jmem_cpointer_t; +#else /* !JERRY_CPOINTER_32_BIT */ +typedef uint16_t jmem_cpointer_t; +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Compressed pointer with tag value + */ +typedef uint32_t jmem_cpointer_tag_t; + +/** + * Memory usage pressure for reclaiming unused memory. + * + * Each failed allocation will try to reclaim memory with increasing pressure, + * until enough memory is freed to fulfill the allocation request. + * + * If not enough memory is freed and JMEM_PRESSURE_FULL is reached, + * then the engine is shut down with JERRY_FATAL_OUT_OF_MEMORY. + */ +typedef enum +{ + JMEM_PRESSURE_NONE, /**< no memory pressure */ + JMEM_PRESSURE_LOW, /**< low memory pressure */ + JMEM_PRESSURE_HIGH, /**< high memory pressure */ + JMEM_PRESSURE_FULL, /**< memory full */ +} jmem_pressure_t; + +/** + * Node for free chunk list + */ +typedef struct jmem_pools_chunk_t +{ + struct jmem_pools_chunk_t *next_p; /**< pointer to next pool chunk */ +} jmem_pools_chunk_t; + +/** + * Free region node + */ +typedef struct +{ + uint32_t next_offset; /**< Offset of next region in list */ + uint32_t size; /**< Size of region */ +} jmem_heap_free_t; + +void jmem_init (void); +void jmem_finalize (void); + +void *jmem_heap_alloc_block (const size_t size); +void *jmem_heap_alloc_block_null_on_error (const size_t size); +void *jmem_heap_realloc_block (void *ptr, const size_t old_size, const size_t new_size); +void jmem_heap_free_block (void *ptr, const size_t size); + + +jmem_cpointer_t JERRY_ATTR_PURE jmem_compress_pointer (const void *pointer_p); +void *JERRY_ATTR_PURE jmem_decompress_pointer (uintptr_t compressed_pointer); + +/** + * Define a local array variable and allocate memory for the array on the heap. + * + * If requested number of elements is zero, assign NULL to the variable. + * + * Warning: + * if there is not enough memory on the heap, shutdown engine with JERRY_FATAL_OUT_OF_MEMORY. + */ +#define JMEM_DEFINE_LOCAL_ARRAY(var_name, number, type) \ + { \ + size_t var_name##___size = (size_t) (number) * sizeof (type); \ + type *var_name = (type *) (jmem_heap_alloc_block (var_name##___size)); + +/** + * Free the previously defined local array variable, freeing corresponding block on the heap, + * if it was allocated (i.e. if the array's size was non-zero). + */ +#define JMEM_FINALIZE_LOCAL_ARRAY(var_name) \ + if (var_name != NULL) \ + { \ + JERRY_ASSERT (var_name##___size != 0); \ + \ + jmem_heap_free_block (var_name, var_name##___size); \ + } \ + else \ + { \ + JERRY_ASSERT (var_name##___size == 0); \ + } \ + } + +/** + * Get value of pointer from specified non-null compressed pointer value + */ +#define JMEM_CP_GET_NON_NULL_POINTER(type, cp_value) ((type *) (jmem_decompress_pointer (cp_value))) + +/** + * Get value of pointer from specified compressed pointer value + */ +#define JMEM_CP_GET_POINTER(type, cp_value) \ + (((JERRY_UNLIKELY ((cp_value) == JMEM_CP_NULL)) ? NULL : JMEM_CP_GET_NON_NULL_POINTER (type, cp_value))) + +/** + * Set value of non-null compressed pointer so that it will correspond + * to specified non_compressed_pointer + */ +#define JMEM_CP_SET_NON_NULL_POINTER(cp_value, non_compressed_pointer) \ + (cp_value) = jmem_compress_pointer (non_compressed_pointer) + +/** + * Set value of compressed pointer so that it will correspond + * to specified non_compressed_pointer + */ +#define JMEM_CP_SET_POINTER(cp_value, non_compressed_pointer) \ + do \ + { \ + void *ptr_value = (void *) non_compressed_pointer; \ + \ + if (JERRY_UNLIKELY ((ptr_value) == NULL)) \ + { \ + (cp_value) = JMEM_CP_NULL; \ + } \ + else \ + { \ + JMEM_CP_SET_NON_NULL_POINTER (cp_value, ptr_value); \ + } \ + } while (false); + +/** + * Set value of pointer-tag value so that it will correspond + * to specified non_compressed_pointer along with tag + */ +#define JMEM_CP_SET_NON_NULL_POINTER_TAG(cp_value, pointer, tag) \ + do \ + { \ + JERRY_ASSERT ((uintptr_t) tag < (uintptr_t) (JMEM_ALIGNMENT)); \ + jmem_cpointer_tag_t compressed_ptr = jmem_compress_pointer (pointer); \ + (cp_value) = (jmem_cpointer_tag_t) ((compressed_ptr << JMEM_TAG_SHIFT) | tag); \ + } while (false); + +/** + * Extract value of pointer from specified pointer-tag value + */ +#define JMEM_CP_GET_NON_NULL_POINTER_FROM_POINTER_TAG(type, cp_value) \ + ((type *) (jmem_decompress_pointer ((cp_value & ~JMEM_TAG_MASK) >> JMEM_TAG_SHIFT))) + +/** + * Extract tag bits from pointer-tag value + */ +#define JMEM_CP_GET_POINTER_TAG_BITS(cp_value) \ + (cp_value & (JMEM_FIRST_TAG_BIT_MASK | JMEM_SECOND_TAG_BIT_MASK | JMEM_THIRD_TAG_BIT_MASK)) + +/** + * Get value of each tag from specified pointer-tag value + */ +#define JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_FIRST_TAG_BIT_MASK) /**< get first tag bit \ + **/ +#define JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_SECOND_TAG_BIT_MASK) /**< get second tag bit **/ +#define JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG(cp_value) \ + (cp_value & JMEM_THIRD_TAG_BIT_MASK) /**< get third tag bit \ + **/ + +/** + * Set value of each tag to specified pointer-tag value + */ +#define JMEM_CP_SET_FIRST_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_FIRST_TAG_BIT_MASK) /**< set first tag bit **/ +#define JMEM_CP_SET_SECOND_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_SECOND_TAG_BIT_MASK) /**< set second tag bit **/ +#define JMEM_CP_SET_THIRD_BIT_TO_POINTER_TAG(cp_value) \ + (cp_value) = (cp_value | JMEM_THIRD_TAG_BIT_MASK) /**< set third tag bit **/ + +/** + * @} + * \addtogroup poolman Memory pool manager + * @{ + */ + +void *jmem_pools_alloc (size_t size); +void jmem_pools_free (void *chunk_p, size_t size); +void jmem_pools_collect_empty (void); + +/** + * @} + * @} + */ + +#endif /* !JMEM_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jmem/meson.build b/src/loaders/lottie/jerryscript/jerry-core/jmem/meson.build new file mode 100644 index 00000000..b95f6dde --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jmem/meson.build @@ -0,0 +1,12 @@ +source_file = [ + 'jmem-allocator-internal.h', + 'jmem.h', + 'jmem-allocator.cpp', + 'jmem-heap.cpp', + 'jmem-poolman.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-bit-fields.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-bit-fields.h new file mode 100644 index 00000000..53ea31b2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-bit-fields.h @@ -0,0 +1,43 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_BIT_FIELDS_H +#define JRT_BIT_FIELDS_H + +/** + * Extract a bit-field. + * + * @param type type of container + * @param container container to extract bit-field from + * @param lsb least significant bit of the value to be extracted + * @param width width of the bit-field to be extracted + * @return bit-field's value + */ +#define JRT_EXTRACT_BIT_FIELD(type, container, lsb, width) (((container) >> lsb) & ((((type) 1) << (width)) - 1)) + +/** + * Set a bit-field. + * + * @param type type of container + * @param container container to insert bit-field to + * @param new_bit_field_value value of bit-field to insert + * @param lsb least significant bit of the value to be inserted + * @param width width of the bit-field to be inserted + * @return bit-field's value + */ +#define JRT_SET_BIT_FIELD_VALUE(type, container, new_bit_field_value, lsb, width) \ + (((container) & ~(((((type) 1) << (width)) - 1) << (lsb))) | (((type) new_bit_field_value) << (lsb))) + +#endif /* !JRT_BIT_FIELDS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-fatals.cpp b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-fatals.cpp new file mode 100644 index 00000000..4ce37293 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-fatals.cpp @@ -0,0 +1,96 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of exit with specified status code. + */ + +#include "jrt-libc-includes.h" +#include "jrt.h" + +/* + * Exit with specified status code. + * + * If !JERRY_NDEBUG and code != 0, print status code with description + * and call assertion fail handler. + */ +void JERRY_ATTR_NORETURN +jerry_fatal (jerry_fatal_code_t code) /**< status code */ +{ +#ifndef JERRY_NDEBUG + switch (code) + { + case JERRY_FATAL_OUT_OF_MEMORY: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_OUT_OF_MEMORY\n"); + break; + } + case JERRY_FATAL_REF_COUNT_LIMIT: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_REF_COUNT_LIMIT\n"); + break; + } + case JERRY_FATAL_UNTERMINATED_GC_LOOPS: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_UNTERMINATED_GC_LOOPS\n"); + break; + } + case JERRY_FATAL_DISABLED_BYTE_CODE: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_DISABLED_BYTE_CODE\n"); + break; + } + case JERRY_FATAL_FAILED_ASSERTION: + { + JERRY_ERROR_MSG ("Error: JERRY_FATAL_FAILED_ASSERTION\n"); + break; + } + } +#endif /* !JERRY_NDEBUG */ + + /* to make compiler happy for some RTOS: 'control reaches end of non-void function' */ + while (true) + { + } +} /* jerry_fatal */ + +#ifndef JERRY_NDEBUG +/** + * Handle failed assertion + */ +void JERRY_ATTR_NORETURN +jerry_assert_fail (const char *assertion, /**< assertion condition string */ + const char *file, /**< file name */ + const char *function, /**< function name */ + const uint32_t line) /**< line */ +{ + JERRY_ERROR_MSG ("ICE: Assertion '%s' failed at %s(%s):%u.\n", assertion, file, function, line); + + jerry_fatal (JERRY_FATAL_FAILED_ASSERTION); +} /* jerry_assert_fail */ + +/** + * Handle execution of control path that should be unreachable + */ +void JERRY_ATTR_NORETURN +jerry_unreachable (const char *file, /**< file name */ + const char *function, /**< function name */ + const uint32_t line) /**< line */ +{ + JERRY_ERROR_MSG ("ICE: Unreachable control path at %s(%s):%u was executed.\n", file, function, line); + + jerry_fatal (JERRY_FATAL_FAILED_ASSERTION); +} /* jerry_unreachable */ +#endif /* !JERRY_NDEBUG */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-libc-includes.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-libc-includes.h new file mode 100644 index 00000000..bf87a86b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-libc-includes.h @@ -0,0 +1,26 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_LIBC_INCLUDES_H +#define JRT_LIBC_INCLUDES_H + +#include +#include +#include +#include +#include +#include + +#endif /* !JRT_LIBC_INCLUDES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-logging.cpp b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-logging.cpp new file mode 100644 index 00000000..512abb6b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-logging.cpp @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jrt.h" + +static jerry_log_level_t jerry_log_level = JERRY_LOG_LEVEL_ERROR; + +/** + * Get current log level + * + * @return log level + */ +jerry_log_level_t +jerry_jrt_get_log_level (void) +{ + return jerry_log_level; +} /* jerry_jrt_get_log_level */ + +/** + * Set log level + * + * @param level: new log level + */ +void +jerry_jrt_set_log_level (jerry_log_level_t level) +{ + jerry_log_level = level; +} /* jerry_jrt_set_log_level */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-types.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-types.h new file mode 100644 index 00000000..16d444e2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt-types.h @@ -0,0 +1,24 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_TYPES_H +#define JRT_TYPES_H + +#include +#include +#include +#include + +#endif /* !JRT_TYPES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt.h b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt.h new file mode 100644 index 00000000..119914ba --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/jrt.h @@ -0,0 +1,229 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JRT_H +#define JRT_H + +#include +#include + +#include "jerryscript-core.h" +#include "jerryscript-port.h" + +#include "jrt-types.h" + +/* + * Constants + */ +#define JERRY_BITSINBYTE 8 + +/* + * Make sure unused parameters, variables, or expressions trigger no compiler warning. + */ +#define JERRY_UNUSED(x) ((void) (x)) + +#define JERRY_UNUSED_1(_1) JERRY_UNUSED (_1) +#define JERRY_UNUSED_2(_1, _2) JERRY_UNUSED (_1), JERRY_UNUSED_1 (_2) +#define JERRY_UNUSED_3(_1, _2, _3) JERRY_UNUSED (_1), JERRY_UNUSED_2 (_2, _3) +#define JERRY_UNUSED_4(_1, _2, _3, _4) JERRY_UNUSED (_1), JERRY_UNUSED_3 (_2, _3, _4) +#define JERRY_UNUSED_5(_1, _2, _3, _4, _5) JERRY_UNUSED (_1), JERRY_UNUSED_4 (_2, _3, _4, _5) +#define JERRY_UNUSED_6(_1, _2, _3, _4, _5, _6) JERRY_UNUSED (_1), JERRY_UNUSED_5 (_2, _3, _4, _5, _6) +#define JERRY_UNUSED_7(_1, _2, _3, _4, _5, _6, _7) JERRY_UNUSED (_1), JERRY_UNUSED_6 (_2, _3, _4, _5, _6, _7) +#define JERRY_UNUSED_8(_1, _2, _3, _4, _5, _6, _7, _8) JERRY_UNUSED (_1), JERRY_UNUSED_7 (_2, _3, _4, _5, _6, _7, _8) + +#define JERRY_VA_ARGS_NUM_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N +#define JERRY_VA_ARGS_NUM(...) JERRY_VA_ARGS_NUM_IMPL (__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +#define JERRY_UNUSED_ALL_IMPL_(nargs) JERRY_UNUSED_##nargs +#define JERRY_UNUSED_ALL_IMPL(nargs) JERRY_UNUSED_ALL_IMPL_ (nargs) +#define JERRY_UNUSED_ALL(...) JERRY_UNUSED_ALL_IMPL (JERRY_VA_ARGS_NUM (__VA_ARGS__)) (__VA_ARGS__) + +/* + * Asserts + * + * Warning: + * Don't use JERRY_STATIC_ASSERT in headers, because + * __LINE__ may be the same for asserts in a header + * and in an implementation file. + */ +#define JERRY_STATIC_ASSERT_GLUE_(a, b, c) a##b##_##c +#define JERRY_STATIC_ASSERT_GLUE(a, b, c) JERRY_STATIC_ASSERT_GLUE_ (a, b, c) +#define JERRY_STATIC_ASSERT(x, msg) \ + enum \ + { \ + JERRY_STATIC_ASSERT_GLUE (static_assertion_failed_, __LINE__, msg) = (!!x) \ + } + +#ifndef JERRY_NDEBUG +void JERRY_ATTR_NORETURN jerry_assert_fail (const char *assertion, + const char *file, + const char *function, + const uint32_t line); +void JERRY_ATTR_NORETURN jerry_unreachable (const char *file, const char *function, const uint32_t line); + +#define JERRY_ASSERT(x) \ + do \ + { \ + if (JERRY_UNLIKELY (!(x))) \ + { \ + jerry_assert_fail (#x, __FILE__, __func__, __LINE__); \ + } \ + } while (0) + +#define JERRY_UNREACHABLE() \ + do \ + { \ + jerry_unreachable (__FILE__, __func__, __LINE__); \ + } while (0) +#else /* JERRY_NDEBUG */ +#define JERRY_ASSERT(x) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED (x); \ + } \ + } while (0) + +#ifdef __GNUC__ +#define JERRY_UNREACHABLE() __builtin_unreachable () +#endif /* __GNUC__ */ + +#ifdef _MSC_VER +#define JERRY_UNREACHABLE() _assume (0) +#endif /* _MSC_VER */ + +#ifndef JERRY_UNREACHABLE +#define JERRY_UNREACHABLE() +#endif /* !JERRY_UNREACHABLE */ + +#endif /* !JERRY_NDEBUG */ + +/** + * Exit on fatal error + */ +void JERRY_ATTR_NORETURN jerry_fatal (jerry_fatal_code_t code); + +jerry_log_level_t jerry_jrt_get_log_level (void); +void jerry_jrt_set_log_level (jerry_log_level_t level); + +/* + * Logging + */ +#if JERRY_LOGGING +#define JERRY_ERROR_MSG(...) jerry_log (JERRY_LOG_LEVEL_ERROR, __VA_ARGS__) +#define JERRY_WARNING_MSG(...) jerry_log (JERRY_LOG_LEVEL_WARNING, __VA_ARGS__) +#define JERRY_DEBUG_MSG(...) jerry_log (JERRY_LOG_LEVEL_DEBUG, __VA_ARGS__) +#define JERRY_TRACE_MSG(...) jerry_log (JERRY_LOG_LEVEL_TRACE, __VA_ARGS__) +#else /* !JERRY_LOGGING */ +#define JERRY_ERROR_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#define JERRY_WARNING_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#define JERRY_DEBUG_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#define JERRY_TRACE_MSG(...) \ + do \ + { \ + if (false) \ + { \ + JERRY_UNUSED_ALL (__VA_ARGS__); \ + } \ + } while (0) +#endif /* JERRY_LOGGING */ + +/** + * Size of struct member + */ +#define JERRY_SIZE_OF_STRUCT_MEMBER(struct_name, member_name) sizeof (((struct_name *) NULL)->member_name) + +/** + * Aligns @a value to @a alignment. @a must be the power of 2. + * + * Returns minimum positive value, that divides @a alignment and is more than or equal to @a value + */ +#define JERRY_ALIGNUP(value, alignment) (((value) + ((alignment) -1)) & ~((alignment) -1)) + +/** + * Align value down + */ +#define JERRY_ALIGNDOWN(value, alignment) ((value) & ~((alignment) -1)) + +/* + * min, max + */ +#define JERRY_MIN(v1, v2) (((v1) < (v2)) ? (v1) : (v2)) +#define JERRY_MAX(v1, v2) (((v1) < (v2)) ? (v2) : (v1)) + +/** + * Calculate the index of the first non-zero bit of a 32 bit integer value + */ +#define JERRY__LOG2_1(n) (((n) >= 2) ? 1 : 0) +#define JERRY__LOG2_2(n) (((n) >= 1 << 2) ? (2 + JERRY__LOG2_1 ((n) >> 2)) : JERRY__LOG2_1 (n)) +#define JERRY__LOG2_4(n) (((n) >= 1 << 4) ? (4 + JERRY__LOG2_2 ((n) >> 4)) : JERRY__LOG2_2 (n)) +#define JERRY__LOG2_8(n) (((n) >= 1 << 8) ? (8 + JERRY__LOG2_4 ((n) >> 8)) : JERRY__LOG2_4 (n)) +#define JERRY_LOG2(n) (((n) >= 1 << 16) ? (16 + JERRY__LOG2_8 ((n) >> 16)) : JERRY__LOG2_8 (n)) + +/** + * JERRY_BLOCK_TAIL_CALL_OPTIMIZATION + * + * Adapted from abseil ( https://github.com/abseil/ ) + * + * Instructs the compiler to avoid optimizing tail-call recursion. This macro is + * useful when you wish to preserve the existing function order within a stack + * trace for logging, debugging, or profiling purposes. + * + * Example: + * + * int f() { + * int result = g(); + * JERRY_BLOCK_TAIL_CALL_OPTIMIZATION(); + * return result; + * } + * + * This macro is intentionally here as jerryscript-compiler.h is a public header and + * it does not make sense to expose this macro to the public. + */ +#if defined(__clang__) || defined(__GNUC__) +/* Clang/GCC will not tail call given inline volatile assembly. */ +#define JERRY_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__ ("") +#else /* !defined(__clang__) && !defined(__GNUC__) */ +/* On GCC 10.x this version also works. */ +#define JERRY_BLOCK_TAIL_CALL_OPTIMIZATION() \ + do \ + { \ + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_API_ENABLED; \ + } while (0) +#endif /* defined(__clang__) || defined (__GNUC__) */ + +#endif /* !JRT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/jrt/meson.build b/src/loaders/lottie/jerryscript/jerry-core/jrt/meson.build new file mode 100644 index 00000000..08b94cf3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/jrt/meson.build @@ -0,0 +1,13 @@ +source_file = [ + 'jrt-bit-fields.h', + 'jrt-libc-includes.h', + 'jrt-types.h', + 'jrt.h', + 'jrt-fatals.cpp', + 'jrt-logging.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.cpp b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.cpp new file mode 100644 index 00000000..fc15f987 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.cpp @@ -0,0 +1,995 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lit-char-helpers.h" + +#include "ecma-helpers.h" + +#include "jerry-config.h" +#include "lit-strings.h" +#include "lit-unicode-ranges-sup.inc.h" +#include "lit-unicode-ranges.inc.h" + +#if JERRY_UNICODE_CASE_CONVERSION +#include "lit-unicode-conversions-sup.inc.h" +#include "lit-unicode-conversions.inc.h" +#include "lit-unicode-folding.inc.h" +#endif /* JERRY_UNICODE_CASE_CONVERSION */ + +#define NUM_OF_ELEMENTS(array) (sizeof (array) / sizeof ((array)[0])) + +/** + * Binary search algorithm that searches the a + * character in the given char array. + * + * @return true - if the character is in the given array + * false - otherwise + */ +#define LIT_SEARCH_CHAR_IN_ARRAY_FN(function_name, char_type, array_type) \ + static bool function_name (char_type c, /**< code unit */ \ + const array_type *array, /**< array */ \ + int size_of_array) /**< length of the array */ \ + { \ + int bottom = 0; \ + int top = size_of_array - 1; \ + \ + while (bottom <= top) \ + { \ + int middle = (bottom + top) / 2; \ + char_type current = array[middle]; \ + \ + if (current == c) \ + { \ + return true; \ + } \ + \ + if (c < current) \ + { \ + top = middle - 1; \ + } \ + else \ + { \ + bottom = middle + 1; \ + } \ + } \ + \ + return false; \ + } /* __function_name */ + +LIT_SEARCH_CHAR_IN_ARRAY_FN (lit_search_char_in_array, ecma_char_t, uint16_t) + +LIT_SEARCH_CHAR_IN_ARRAY_FN (lit_search_codepoint_in_array, lit_code_point_t, uint32_t) + +/** + * Binary search algorithm that searches a character in the given intervals. + * Intervals specifed by two arrays. The first one contains the starting points + * of the intervals, the second one contains the length of them. + * + * @return true - if the the character is included (inclusively) in one of the intervals in the given array + * false - otherwise + */ +#define LIT_SEARCH_CHAR_IN_INTERVAL_ARRAY_FN(function_name, char_type, array_type, interval_type) \ + static bool function_name (char_type c, /**< code unit */ \ + const array_type *array_sp, /**< array of interval starting points */ \ + const interval_type *lengths, /**< array of interval lengths */ \ + int size_of_array) /**< length of the array */ \ + { \ + int bottom = 0; \ + int top = size_of_array - 1; \ + \ + while (bottom <= top) \ + { \ + int middle = (bottom + top) / 2; \ + char_type current_sp = array_sp[middle]; \ + \ + if (current_sp <= c && c <= current_sp + lengths[middle]) \ + { \ + return true; \ + } \ + \ + if (c > current_sp) \ + { \ + bottom = middle + 1; \ + } \ + else \ + { \ + top = middle - 1; \ + } \ + } \ + \ + return false; \ + } /* function_name */ + +LIT_SEARCH_CHAR_IN_INTERVAL_ARRAY_FN (lit_search_char_in_interval_array, ecma_char_t, uint16_t, uint8_t) + +LIT_SEARCH_CHAR_IN_INTERVAL_ARRAY_FN (lit_search_codepoint_in_interval_array, lit_code_point_t, uint32_t, uint16_t) + +/** + * Check if specified character is one of the Whitespace characters including those that fall into + * "Space, Separator" ("Zs") Unicode character category or one of the Line Terminator characters. + * + * @return true - if the character is one of characters, listed in ECMA-262 v5, Table 2, + * false - otherwise + */ +bool +lit_char_is_white_space (lit_code_point_t c) /**< code point */ +{ + if (c <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + return (c == LIT_CHAR_SP || (c >= LIT_CHAR_TAB && c <= LIT_CHAR_CR)); + } + + if (c == LIT_CHAR_BOM || c == LIT_CHAR_LS || c == LIT_CHAR_PS) + { + return true; + } + + return (c <= LIT_UTF16_CODE_UNIT_MAX + && ((c >= lit_unicode_white_space_interval_starts[0] + && c <= lit_unicode_white_space_interval_starts[0] + lit_unicode_white_space_interval_lengths[0]) + || lit_search_char_in_array ((ecma_char_t) c, + lit_unicode_white_space_chars, + NUM_OF_ELEMENTS (lit_unicode_white_space_chars)))); +} /* lit_char_is_white_space */ + +/** + * Check if specified character is one of LineTerminator characters + * + * @return true - if the character is one of characters, listed in ECMA-262 v5, Table 3, + * false - otherwise + */ +bool +lit_char_is_line_terminator (ecma_char_t c) /**< code unit */ +{ + return (c == LIT_CHAR_LF || c == LIT_CHAR_CR || c == LIT_CHAR_LS || c == LIT_CHAR_PS); +} /* lit_char_is_line_terminator */ + +/** + * Check if specified character is a Unicode ID_Start + * + * See also: + * ECMA-262 v1, 11.6: UnicodeIDStart + * + * @return true - if the codepoint has Unicode property "ID_Start" + * false - otherwise + */ +static bool +lit_char_is_unicode_id_start (lit_code_point_t code_point) /**< code unit */ +{ + if (JERRY_UNLIKELY (code_point >= LIT_UTF8_4_BYTE_CODE_POINT_MIN)) + { + return (lit_search_codepoint_in_interval_array (code_point, + lit_unicode_id_start_interval_starts_sup, + lit_unicode_id_start_interval_lengths_sup, + NUM_OF_ELEMENTS (lit_unicode_id_start_interval_starts_sup)) + || lit_search_codepoint_in_array (code_point, + lit_unicode_id_start_chars_sup, + NUM_OF_ELEMENTS (lit_unicode_id_start_chars_sup))); + } + ecma_char_t c = (ecma_char_t) code_point; + + return (lit_search_char_in_interval_array (c, + lit_unicode_id_start_interval_starts, + lit_unicode_id_start_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_id_start_interval_starts)) + || lit_search_char_in_array (c, lit_unicode_id_start_chars, NUM_OF_ELEMENTS (lit_unicode_id_start_chars))); +} /* lit_char_is_unicode_id_start */ + +/** + * Check if specified character is a Unicode ID_Continue + * + * See also: + * ECMA-262 v1, 11.6: UnicodeIDContinue + * + * @return true - if the codepoint has Unicode property "ID_Continue" + * false - otherwise + */ +static bool +lit_char_is_unicode_id_continue (lit_code_point_t code_point) /**< code unit */ +{ + /* Each ID_Start codepoint is ID_Continue as well. */ + if (lit_char_is_unicode_id_start (code_point)) + { + return true; + } + + if (JERRY_UNLIKELY (code_point >= LIT_UTF8_4_BYTE_CODE_POINT_MIN)) + { + return (lit_search_codepoint_in_interval_array (code_point, + lit_unicode_id_continue_interval_starts_sup, + lit_unicode_id_continue_interval_lengths_sup, + NUM_OF_ELEMENTS (lit_unicode_id_continue_interval_starts_sup)) + || lit_search_codepoint_in_array (code_point, + lit_unicode_id_continue_chars_sup, + NUM_OF_ELEMENTS (lit_unicode_id_continue_chars_sup))); + } + ecma_char_t c = (ecma_char_t) code_point; + + return ( + lit_search_char_in_interval_array (c, + lit_unicode_id_continue_interval_starts, + lit_unicode_id_continue_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_id_continue_interval_starts)) + || lit_search_char_in_array (c, lit_unicode_id_continue_chars, NUM_OF_ELEMENTS (lit_unicode_id_continue_chars))); +} /* lit_char_is_unicode_id_continue */ + +/** + * Checks whether the character is a valid identifier start. + * + * @return true if it is. + */ +bool +lit_code_point_is_identifier_start (lit_code_point_t code_point) /**< code point */ +{ + /* Fast path for ASCII-defined letters. */ + if (code_point <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + return ((LEXER_TO_ASCII_LOWERCASE (code_point) >= LIT_CHAR_LOWERCASE_A + && LEXER_TO_ASCII_LOWERCASE (code_point) <= LIT_CHAR_LOWERCASE_Z) + || code_point == LIT_CHAR_DOLLAR_SIGN || code_point == LIT_CHAR_UNDERSCORE); + } + + return lit_char_is_unicode_id_start (code_point); +} /* lit_code_point_is_identifier_start */ + +/** + * Checks whether the character is a valid identifier part. + * + * @return true if it is. + */ +bool +lit_code_point_is_identifier_part (lit_code_point_t code_point) /**< code point */ +{ + /* Fast path for ASCII-defined letters. */ + if (code_point <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + return ((LEXER_TO_ASCII_LOWERCASE (code_point) >= LIT_CHAR_LOWERCASE_A + && LEXER_TO_ASCII_LOWERCASE (code_point) <= LIT_CHAR_LOWERCASE_Z) + || (code_point >= LIT_CHAR_0 && code_point <= LIT_CHAR_9) || code_point == LIT_CHAR_DOLLAR_SIGN + || code_point == LIT_CHAR_UNDERSCORE); + } + + return lit_char_is_unicode_id_continue (code_point); +} /* lit_code_point_is_identifier_part */ + +/** + * Check if specified character is one of OctalDigit characters (ECMA-262 v5, B.1.2) + * + * @return true / false + */ +bool +lit_char_is_octal_digit (ecma_char_t c) /**< code unit */ +{ + return (c >= LIT_CHAR_ASCII_OCTAL_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_OCTAL_DIGITS_END); +} /* lit_char_is_octal_digit */ + +/** + * Check if specified character is one of DecimalDigit characters (ECMA-262 v5, 7.8.3) + * + * @return true / false + */ +bool +lit_char_is_decimal_digit (ecma_char_t c) /**< code unit */ +{ + return (c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END); +} /* lit_char_is_decimal_digit */ + +/** + * Check if specified character is one of HexDigit characters (ECMA-262 v5, 7.8.3) + * + * @return true / false + */ +bool +lit_char_is_hex_digit (ecma_char_t c) /**< code unit */ +{ + return ((c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END) + || (LEXER_TO_ASCII_LOWERCASE (c) >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_BEGIN + && LEXER_TO_ASCII_LOWERCASE (c) <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_END)); +} /* lit_char_is_hex_digit */ + +/** + * Check if specified character is one of BinaryDigits characters (ECMA-262 v6, 11.8.3) + * + * @return true / false + */ +bool +lit_char_is_binary_digit (ecma_char_t c) /** code unit */ +{ + return (c == LIT_CHAR_0 || c == LIT_CHAR_1); +} /* lit_char_is_binary_digit */ + +/** + * @return radix value + */ +uint8_t +lit_char_to_radix (lit_utf8_byte_t c) /** code unit */ +{ + switch (LEXER_TO_ASCII_LOWERCASE (c)) + { + case LIT_CHAR_LOWERCASE_X: + { + return 16; + } + case LIT_CHAR_LOWERCASE_O: + { + return 8; + } + case LIT_CHAR_LOWERCASE_B: + { + return 2; + } + default: + { + return 10; + } + } +} /* lit_char_to_radix */ + +/** + * UnicodeEscape abstract method + * + * See also: ECMA-262 v10, 24.5.2.3 + */ +void +lit_char_unicode_escape (ecma_stringbuilder_t *builder_p, /**< stringbuilder to append */ + ecma_char_t c) /**< code unit to convert */ +{ + ecma_stringbuilder_append_raw (builder_p, (lit_utf8_byte_t *) "\\u", 2); + + for (int8_t i = 3; i >= 0; i--) + { + int32_t result_char = (c >> (i * 4)) & 0xF; + ecma_stringbuilder_append_byte ( + builder_p, + (lit_utf8_byte_t) (result_char + (result_char <= 9 ? LIT_CHAR_0 : (LIT_CHAR_LOWERCASE_A - 10)))); + } +} /* lit_char_unicode_escape */ + +/** + * Convert a HexDigit character to its numeric value, as defined in ECMA-262 v5, 7.8.3 + * + * @return digit value, corresponding to the hex char + */ +uint32_t +lit_char_hex_to_int (ecma_char_t c) /**< code unit, corresponding to + * one of HexDigit characters */ +{ + JERRY_ASSERT (lit_char_is_hex_digit (c)); + + if (c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END) + { + return (uint32_t) (c - LIT_CHAR_ASCII_DIGITS_BEGIN); + } + + const uint32_t hex_offset = 10 - (LIT_CHAR_LOWERCASE_A % 32); + return (c % 32) + hex_offset; +} /* lit_char_hex_to_int */ + +/** + * Converts a character to UTF8 bytes. + * + * @return length of the UTF8 representation. + */ +size_t +lit_code_point_to_cesu8_bytes (uint8_t *dst_p, /**< destination buffer */ + lit_code_point_t code_point) /**< code point */ +{ + if (code_point < LIT_UTF8_2_BYTE_CODE_POINT_MIN) + { + /* 00000000 0xxxxxxx -> 0xxxxxxx */ + dst_p[0] = (uint8_t) code_point; + return 1; + } + + if (code_point < LIT_UTF8_3_BYTE_CODE_POINT_MIN) + { + /* 00000yyy yyxxxxxx -> 110yyyyy 10xxxxxx */ + dst_p[0] = (uint8_t) (LIT_UTF8_2_BYTE_MARKER | ((code_point >> 6) & LIT_UTF8_LAST_5_BITS_MASK)); + dst_p[1] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | (code_point & LIT_UTF8_LAST_6_BITS_MASK)); + return 2; + } + + if (code_point < LIT_UTF8_4_BYTE_CODE_POINT_MIN) + { + /* zzzzyyyy yyxxxxxx -> 1110zzzz 10yyyyyy 10xxxxxx */ + dst_p[0] = (uint8_t) (LIT_UTF8_3_BYTE_MARKER | ((code_point >> 12) & LIT_UTF8_LAST_4_BITS_MASK)); + dst_p[1] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | ((code_point >> 6) & LIT_UTF8_LAST_6_BITS_MASK)); + dst_p[2] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | (code_point & LIT_UTF8_LAST_6_BITS_MASK)); + return 3; + } + + JERRY_ASSERT (code_point <= LIT_UNICODE_CODE_POINT_MAX); + + code_point -= LIT_UTF8_4_BYTE_CODE_POINT_MIN; + + dst_p[0] = (uint8_t) (LIT_UTF8_3_BYTE_MARKER | 0xd); + dst_p[1] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | 0x20 | ((code_point >> 16) & LIT_UTF8_LAST_4_BITS_MASK)); + dst_p[2] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | ((code_point >> 10) & LIT_UTF8_LAST_6_BITS_MASK)); + + dst_p[3] = (uint8_t) (LIT_UTF8_3_BYTE_MARKER | 0xd); + dst_p[4] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | 0x30 | ((code_point >> 6) & LIT_UTF8_LAST_4_BITS_MASK)); + dst_p[5] = (uint8_t) (LIT_UTF8_EXTRA_BYTE_MARKER | (code_point & LIT_UTF8_LAST_6_BITS_MASK)); + + return 3 * 2; +} /* lit_code_point_to_cesu8_bytes */ + +/** + * Returns the length of the UTF8 representation of a character. + * + * @return length of the UTF8 representation. + */ +size_t +lit_code_point_get_cesu8_length (lit_code_point_t code_point) /**< code point */ +{ + if (code_point < LIT_UTF8_2_BYTE_CODE_POINT_MIN) + { + /* 00000000 0xxxxxxx */ + return 1; + } + + if (code_point < LIT_UTF8_3_BYTE_CODE_POINT_MIN) + { + /* 00000yyy yyxxxxxx */ + return 2; + } + + if (code_point < LIT_UTF8_4_BYTE_CODE_POINT_MIN) + { + /* zzzzyyyy yyxxxxxx */ + return 3; + } + + /* high + low surrogate */ + return 2 * 3; +} /* lit_code_point_get_cesu8_length */ + +/** + * Convert a four byte long utf8 character to two three byte long cesu8 characters + */ +void +lit_four_byte_utf8_char_to_cesu8 (uint8_t *dst_p, /**< destination buffer */ + const uint8_t *source_p) /**< source buffer */ +{ + lit_code_point_t code_point = ((((uint32_t) source_p[0]) & LIT_UTF8_LAST_3_BITS_MASK) << 18); + code_point |= ((((uint32_t) source_p[1]) & LIT_UTF8_LAST_6_BITS_MASK) << 12); + code_point |= ((((uint32_t) source_p[2]) & LIT_UTF8_LAST_6_BITS_MASK) << 6); + code_point |= (((uint32_t) source_p[3]) & LIT_UTF8_LAST_6_BITS_MASK); + + lit_code_point_to_cesu8_bytes (dst_p, code_point); +} /* lit_four_byte_utf8_char_to_cesu8 */ + +/** + * Lookup hex digits in a buffer + * + * @return UINT32_MAX - if next 'lookup' number of characters do not form a valid hex number + * value of hex number, otherwise + */ +uint32_t +lit_char_hex_lookup (const lit_utf8_byte_t *buf_p, /**< buffer */ + const lit_utf8_byte_t *const buf_end_p, /**< buffer end */ + uint32_t lookup) /**< size of lookup */ +{ + JERRY_ASSERT (lookup <= 4); + + if (JERRY_UNLIKELY (buf_p + lookup > buf_end_p)) + { + return UINT32_MAX; + } + + uint32_t value = 0; + + while (lookup--) + { + lit_utf8_byte_t ch = *buf_p++; + if (!lit_char_is_hex_digit (ch)) + { + return UINT32_MAX; + } + + value <<= 4; + value += lit_char_hex_to_int (ch); + } + + JERRY_ASSERT (value <= LIT_UTF16_CODE_UNIT_MAX); + return value; +} /* lit_char_hex_lookup */ + +/** + * Parse a decimal number with the value clamped to UINT32_MAX. + * + * @returns uint32_t number + */ +uint32_t +lit_parse_decimal (const lit_utf8_byte_t **buffer_p, /**< [in/out] character buffer */ + const lit_utf8_byte_t *buffer_end_p) /**< buffer end */ +{ + const lit_utf8_byte_t *current_p = *buffer_p; + JERRY_ASSERT (lit_char_is_decimal_digit (*current_p)); + + uint32_t value = (uint32_t) (*current_p++ - LIT_CHAR_0); + + while (current_p < buffer_end_p && lit_char_is_decimal_digit (*current_p)) + { + const uint32_t digit = (uint32_t) (*current_p++ - LIT_CHAR_0); + uint32_t new_value = value * 10 + digit; + + if (JERRY_UNLIKELY (value > UINT32_MAX / 10) || JERRY_UNLIKELY (new_value < value)) + { + value = UINT32_MAX; + continue; + } + + value = new_value; + } + + *buffer_p = current_p; + return value; +} /* lit_parse_decimal */ + +/** + * Check if specified character is a word character (part of IsWordChar abstract operation) + * + * See also: ECMA-262 v5, 15.10.2.6 (IsWordChar) + * + * @return true - if the character is a word character + * false - otherwise + */ +bool +lit_char_is_word_char (lit_code_point_t c) /**< code point */ +{ + return ((c >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN && c <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_END) + || (c >= LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN && c <= LIT_CHAR_ASCII_UPPERCASE_LETTERS_END) + || (c >= LIT_CHAR_ASCII_DIGITS_BEGIN && c <= LIT_CHAR_ASCII_DIGITS_END) || c == LIT_CHAR_UNDERSCORE); +} /* lit_char_is_word_char */ + +#if JERRY_UNICODE_CASE_CONVERSION + +/** + * Check if the specified character is in one of those tables which contain bidirectional conversions. + * + * @return codepoint of the converted character if it is found the the tables + * LIT_INVALID_CP - otherwise. + */ +static lit_code_point_t +lit_search_in_bidirectional_conversion_tables (lit_code_point_t cp, /**< code point */ + bool is_lowercase) /**< is lowercase conversion */ +{ + /* 1, Check if the specified character is part of the lit_unicode_character_case_ranges_{sup} table. */ + int number_of_case_ranges; + bool is_supplementary = cp > LIT_UTF16_CODE_UNIT_MAX; + + if (is_supplementary) + { + number_of_case_ranges = NUM_OF_ELEMENTS (lit_unicode_character_case_ranges_sup); + } + else + { + number_of_case_ranges = NUM_OF_ELEMENTS (lit_unicode_character_case_ranges); + } + + int conv_counter = 0; + + for (int i = 0; i < number_of_case_ranges; i++) + { + if (i % 2 == 0 && i > 0) + { + conv_counter++; + } + + size_t range_length; + lit_code_point_t start_point; + + if (is_supplementary) + { + range_length = lit_unicode_character_case_range_lengths_sup[conv_counter]; + start_point = lit_unicode_character_case_ranges_sup[i]; + } + else + { + range_length = lit_unicode_character_case_range_lengths[conv_counter]; + start_point = lit_unicode_character_case_ranges[i]; + } + + if (start_point > cp || cp >= start_point + range_length) + { + continue; + } + + uint32_t char_dist = (uint32_t) cp - start_point; + int offset; + if (i % 2 == 0) + { + if (!is_lowercase) + { + return cp; + } + + offset = i + 1; + } + else + { + if (is_lowercase) + { + return cp; + } + + offset = i - 1; + } + + if (is_supplementary) + { + start_point = lit_unicode_character_case_ranges_sup[offset]; + } + else + { + start_point = lit_unicode_character_case_ranges[offset]; + } + + return (lit_code_point_t) (start_point + char_dist); + } + + /* Note: After this point based on the latest unicode standard(13.0.0.6) no conversion characters are + defined for supplementary planes */ + if (is_supplementary) + { + return cp; + } + + /* 2, Check if the specified character is part of the character_pair_ranges table. */ + int bottom = 0; + int top = NUM_OF_ELEMENTS (lit_unicode_character_pair_ranges) - 1; + + while (bottom <= top) + { + int middle = (bottom + top) / 2; + lit_code_point_t current_sp = lit_unicode_character_pair_ranges[middle]; + + if (current_sp <= cp && cp < current_sp + lit_unicode_character_pair_range_lengths[middle]) + { + uint32_t char_dist = (uint32_t) (cp - current_sp); + + if ((cp - current_sp) % 2 == 0) + { + return is_lowercase ? (lit_code_point_t) (current_sp + char_dist + 1) : cp; + } + + return is_lowercase ? cp : (lit_code_point_t) (current_sp + char_dist - 1); + } + + if (cp > current_sp) + { + bottom = middle + 1; + } + else + { + top = middle - 1; + } + } + + /* 3, Check if the specified character is part of the character_pairs table. */ + int number_of_character_pairs = NUM_OF_ELEMENTS (lit_unicode_character_pairs); + + for (int i = 0; i < number_of_character_pairs; i++) + { + if (cp != lit_unicode_character_pairs[i]) + { + continue; + } + + if (i % 2 == 0) + { + return is_lowercase ? lit_unicode_character_pairs[i + 1] : cp; + } + + return is_lowercase ? cp : lit_unicode_character_pairs[i - 1]; + } + + return LIT_INVALID_CP; +} /* lit_search_in_bidirectional_conversion_tables */ + +/** + * Check if the specified character is in the given conversion table. + * + * @return LIT_MULTIPLE_CU if the converted character consist more than a single code unit + * converted code point - otherwise + */ +static lit_code_point_t +lit_search_in_conversion_table (ecma_char_t character, /**< code unit */ + ecma_stringbuilder_t *builder_p, /**< string builder */ + const ecma_char_t *array, /**< array */ + const uint8_t *counters) /**< case_values counter */ +{ + int end_point = 0; + + for (int i = 0; i < 3; i++) + { + int start_point = end_point; + int size_of_case_value = i + 1; + end_point += counters[i] * (size_of_case_value + 1); + + int bottom = start_point; + int top = end_point - size_of_case_value; + + while (bottom <= top) + { + int middle = (bottom + top) / 2; + + middle -= ((middle - bottom) % (size_of_case_value + 1)); + + ecma_char_t current = array[middle]; + + if (current == character) + { + if (builder_p != NULL) + { + ecma_stringbuilder_append_char (builder_p, array[middle + 1]); + + if (size_of_case_value > 1) + { + ecma_stringbuilder_append_char (builder_p, array[middle + 2]); + } + if (size_of_case_value > 2) + { + ecma_stringbuilder_append_char (builder_p, array[middle + 3]); + } + } + + return size_of_case_value == 1 ? array[middle + 1] : LIT_MULTIPLE_CU; + } + + if (character < current) + { + top = middle - (size_of_case_value + 1); + } + else + { + bottom = middle + (size_of_case_value + 1); + } + } + } + + if (builder_p != NULL) + { + ecma_stringbuilder_append_char (builder_p, character); + } + + return (lit_code_point_t) character; +} /* lit_search_in_conversion_table */ +#endif /* JERRY_UNICODE_CASE_CONVERSION */ + +/** + * Append the converted lowercase codeunit sequence of an a given codepoint into the stringbuilder if it is present. + * + * @return LIT_MULTIPLE_CU if the converted codepoint consist more than a single code unit + * converted code point - otherwise + */ +lit_code_point_t +lit_char_to_lower_case (lit_code_point_t cp, /**< code point */ + ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + if (cp <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (cp >= LIT_CHAR_UPPERCASE_A && cp <= LIT_CHAR_UPPERCASE_Z) + { + cp = (lit_utf8_byte_t) (cp + (LIT_CHAR_LOWERCASE_A - LIT_CHAR_UPPERCASE_A)); + } + + if (builder_p != NULL) + { + ecma_stringbuilder_append_byte (builder_p, (lit_utf8_byte_t) cp); + } + + return cp; + } + +#if JERRY_UNICODE_CASE_CONVERSION + lit_code_point_t lowercase_cp = lit_search_in_bidirectional_conversion_tables (cp, true); + + if (lowercase_cp != LIT_INVALID_CP) + { + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, lowercase_cp); + } + + return lowercase_cp; + } + + JERRY_ASSERT (cp < LIT_UTF8_4_BYTE_CODE_POINT_MIN); + + int num_of_lowercase_ranges = NUM_OF_ELEMENTS (lit_unicode_lower_case_ranges); + + for (int i = 0, j = 0; i < num_of_lowercase_ranges; i += 2, j++) + { + JERRY_ASSERT (lit_unicode_lower_case_range_lengths[j] > 0); + uint32_t range_length = (uint32_t) (lit_unicode_lower_case_range_lengths[j] - 1); + lit_code_point_t start_point = lit_unicode_lower_case_ranges[i]; + + if (start_point <= cp && cp <= start_point + range_length) + { + lowercase_cp = lit_unicode_lower_case_ranges[i + 1] + (cp - start_point); + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, lowercase_cp); + } + + return lowercase_cp; + } + } + + return lit_search_in_conversion_table ((ecma_char_t) cp, + builder_p, + lit_unicode_lower_case_conversions, + lit_unicode_lower_case_conversion_counters); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, cp); + } + + return cp; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_to_lower_case */ + +/** + * Append the converted uppercase codeunit sequence of an a given codepoint into the stringbuilder if it is present. + * + * @return LIT_MULTIPLE_CU if the converted codepoint consist more than a single code unit + * converted code point - otherwise + */ +lit_code_point_t +lit_char_to_upper_case (lit_code_point_t cp, /**< code point */ + ecma_stringbuilder_t *builder_p) /**< string builder */ +{ + if (cp <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + if (cp >= LIT_CHAR_LOWERCASE_A && cp <= LIT_CHAR_LOWERCASE_Z) + { + cp = (lit_utf8_byte_t) (cp - (LIT_CHAR_LOWERCASE_A - LIT_CHAR_UPPERCASE_A)); + } + + if (builder_p != NULL) + { + ecma_stringbuilder_append_byte (builder_p, (lit_utf8_byte_t) cp); + } + + return cp; + } + +#if JERRY_UNICODE_CASE_CONVERSION + lit_code_point_t uppercase_cp = lit_search_in_bidirectional_conversion_tables (cp, false); + + if (uppercase_cp != LIT_INVALID_CP) + { + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, uppercase_cp); + } + + return uppercase_cp; + } + + int num_of_upper_case_special_ranges = NUM_OF_ELEMENTS (lit_unicode_upper_case_special_ranges); + + for (int i = 0, j = 0; i < num_of_upper_case_special_ranges; i += 3, j++) + { + uint32_t range_length = lit_unicode_upper_case_special_range_lengths[j]; + ecma_char_t start_point = lit_unicode_upper_case_special_ranges[i]; + + if (start_point <= cp && cp <= start_point + range_length) + { + if (builder_p != NULL) + { + uppercase_cp = lit_unicode_upper_case_special_ranges[i + 1] + (cp - start_point); + ecma_stringbuilder_append_codepoint (builder_p, uppercase_cp); + ecma_stringbuilder_append_codepoint (builder_p, lit_unicode_upper_case_special_ranges[i + 2]); + } + + return LIT_MULTIPLE_CU; + } + } + + return lit_search_in_conversion_table ((ecma_char_t) cp, + builder_p, + lit_unicode_upper_case_conversions, + lit_unicode_upper_case_conversion_counters); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + if (builder_p != NULL) + { + ecma_stringbuilder_append_codepoint (builder_p, cp); + } + + return cp; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_to_upper_case */ + +/* + * Look up whether the character should be folded to the lowercase variant. + * + * @return true, if character should be lowercased + * false, otherwise + */ +bool +lit_char_fold_to_lower (lit_code_point_t cp) /**< code point */ +{ +#if JERRY_UNICODE_CASE_CONVERSION + return (cp <= LIT_UTF8_1_BYTE_CODE_POINT_MAX || cp > LIT_UTF16_CODE_UNIT_MAX + || (!lit_search_char_in_interval_array ((ecma_char_t) cp, + lit_unicode_folding_skip_to_lower_interval_starts, + lit_unicode_folding_skip_to_lower_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_folding_skip_to_lower_interval_starts)) + && !lit_search_char_in_array ((ecma_char_t) cp, + lit_unicode_folding_skip_to_lower_chars, + NUM_OF_ELEMENTS (lit_unicode_folding_skip_to_lower_chars)))); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + return true; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_fold_to_lower */ + +/* + * Look up whether the character should be folded to the uppercase variant. + * + * @return true, if character should be uppercased + * false, otherwise + */ +bool +lit_char_fold_to_upper (lit_code_point_t cp) /**< code point */ +{ +#if JERRY_UNICODE_CASE_CONVERSION + return (cp > LIT_UTF8_1_BYTE_CODE_POINT_MAX && cp <= LIT_UTF16_CODE_UNIT_MAX + && (lit_search_char_in_interval_array ((ecma_char_t) cp, + lit_unicode_folding_to_upper_interval_starts, + lit_unicode_folding_to_upper_interval_lengths, + NUM_OF_ELEMENTS (lit_unicode_folding_to_upper_interval_starts)) + || lit_search_char_in_array ((ecma_char_t) cp, + lit_unicode_folding_to_upper_chars, + NUM_OF_ELEMENTS (lit_unicode_folding_to_upper_chars)))); +#else /* !JERRY_UNICODE_CASE_CONVERSION */ + return false; +#endif /* JERRY_UNICODE_CASE_CONVERSION */ +} /* lit_char_fold_to_upper */ + +/** + * Helper method to find a specific character in a string + * + * Used by: + * ecma_builtin_string_prototype_object_replace_helper + * + * @return true - if the given character is in the string + * false - otherwise + */ +bool +lit_find_char_in_string (ecma_string_t *str_p, /**< source string */ + lit_utf8_byte_t c) /**< character to find*/ +{ + ECMA_STRING_TO_UTF8_STRING (str_p, start_p, start_size); + + const lit_utf8_byte_t *str_curr_p = start_p; + const lit_utf8_byte_t *str_end_p = start_p + start_size; + bool have_char = false; + + while (str_curr_p < str_end_p) + { + if (*str_curr_p++ == c) + { + have_char = true; + break; + } + } + + ECMA_FINALIZE_UTF8_STRING (start_p, start_size); + + return have_char; +} /* lit_find_char_in_string */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.h new file mode 100644 index 00000000..9b696177 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-char-helpers.h @@ -0,0 +1,260 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_CHAR_HELPERS_H +#define LIT_CHAR_HELPERS_H + +#include "ecma-globals.h" + +#include "lit-globals.h" + +/** + * Invalid character code point + */ +#define LIT_INVALID_CP 0xFFFFFFFF + +/** + * Result of lit_char_to_lower_case/lit_char_to_upper_case consist more than of a single code unit + */ +#define LIT_MULTIPLE_CU 0xFFFFFFFE + +/* + * Format control characters (ECMA-262 v5, Table 1) + */ +#define LIT_CHAR_ZWNJ ((ecma_char_t) 0x200C) /* zero width non-joiner */ +#define LIT_CHAR_ZWJ ((ecma_char_t) 0x200D) /* zero width joiner */ +#define LIT_CHAR_BOM ((ecma_char_t) 0xFEFF) /* byte order mark */ + +/* + * Whitespace characters (ECMA-262 v5, Table 2) + */ +#define LIT_CHAR_TAB ((ecma_char_t) 0x0009) /* tab */ +#define LIT_CHAR_VTAB ((ecma_char_t) 0x000B) /* vertical tab */ +#define LIT_CHAR_FF ((ecma_char_t) 0x000C) /* form feed */ +#define LIT_CHAR_SP ((ecma_char_t) 0x0020) /* space */ +#define LIT_CHAR_NBSP ((ecma_char_t) 0x00A0) /* no-break space */ +#define LIT_CHAR_MVS ((ecma_char_t) 0x180E) /* mongolian vowel separator */ +/* LIT_CHAR_BOM is defined above */ + +bool lit_char_is_white_space (lit_code_point_t c); + +/* + * Line terminator characters (ECMA-262 v5, Table 3) + */ +#define LIT_CHAR_LF ((ecma_char_t) 0x000A) /* line feed */ +#define LIT_CHAR_CR ((ecma_char_t) 0x000D) /* carriage return */ +#define LIT_CHAR_LS ((ecma_char_t) 0x2028) /* line separator */ +#define LIT_CHAR_PS ((ecma_char_t) 0x2029) /* paragraph separator */ + +bool lit_char_is_line_terminator (ecma_char_t c); + +/* + * String Single Character Escape Sequences (ECMA-262 v5, Table 4) + */ +#define LIT_CHAR_BS ((ecma_char_t) 0x0008) /* backspace */ +/* LIT_CHAR_TAB is defined above */ +/* LIT_CHAR_LF is defined above */ +/* LIT_CHAR_VTAB is defined above */ +/* LIT_CHAR_FF is defined above */ +/* LIT_CHAR_CR is defined above */ +#define LIT_CHAR_DOUBLE_QUOTE ((ecma_char_t) '"') /* double quote */ +#define LIT_CHAR_SINGLE_QUOTE ((ecma_char_t) '\'') /* single quote */ +#define LIT_CHAR_BACKSLASH ((ecma_char_t) '\\') /* reverse solidus (backslash) */ + +/* + * Comment characters (ECMA-262 v5, 7.4) + */ +#define LIT_CHAR_SLASH ((ecma_char_t) '/') /* solidus */ +#define LIT_CHAR_ASTERISK ((ecma_char_t) '*') /* asterisk */ + +/* + * Identifier name characters (ECMA-262 v5, 7.6) + */ +#define LIT_CHAR_DOLLAR_SIGN ((ecma_char_t) '$') /* dollar sign */ +#define LIT_CHAR_UNDERSCORE ((ecma_char_t) '_') /* low line (underscore) */ +/* LIT_CHAR_BACKSLASH defined above */ + +bool lit_code_point_is_identifier_start (lit_code_point_t code_point); +bool lit_code_point_is_identifier_part (lit_code_point_t code_point); + +/* + * Punctuator characters (ECMA-262 v5, 7.7) + */ +#define LIT_CHAR_LEFT_BRACE ((ecma_char_t) '{') /* left curly bracket */ +#define LIT_CHAR_RIGHT_BRACE ((ecma_char_t) '}') /* right curly bracket */ +#define LIT_CHAR_LEFT_PAREN ((ecma_char_t) '(') /* left parenthesis */ +#define LIT_CHAR_RIGHT_PAREN ((ecma_char_t) ')') /* right parenthesis */ +#define LIT_CHAR_LEFT_SQUARE ((ecma_char_t) '[') /* left square bracket */ +#define LIT_CHAR_RIGHT_SQUARE ((ecma_char_t) ']') /* right square bracket */ +#define LIT_CHAR_DOT ((ecma_char_t) '.') /* dot */ +#define LIT_CHAR_SEMICOLON ((ecma_char_t) ';') /* semicolon */ +#define LIT_CHAR_COMMA ((ecma_char_t) ',') /* comma */ +#define LIT_CHAR_LESS_THAN ((ecma_char_t) '<') /* less-than sign */ +#define LIT_CHAR_GREATER_THAN ((ecma_char_t) '>') /* greater-than sign */ +#define LIT_CHAR_EQUALS ((ecma_char_t) '=') /* equals sign */ +#define LIT_CHAR_PLUS ((ecma_char_t) '+') /* plus sign */ +#define LIT_CHAR_MINUS ((ecma_char_t) '-') /* hyphen-minus */ +/* LIT_CHAR_ASTERISK is defined above */ +#define LIT_CHAR_PERCENT ((ecma_char_t) '%') /* percent sign */ +#define LIT_CHAR_AMPERSAND ((ecma_char_t) '&') /* ampersand */ +#define LIT_CHAR_VLINE ((ecma_char_t) '|') /* vertical line */ +#define LIT_CHAR_CIRCUMFLEX ((ecma_char_t) '^') /* circumflex accent */ +#define LIT_CHAR_EXCLAMATION ((ecma_char_t) '!') /* exclamation mark */ +#define LIT_CHAR_TILDE ((ecma_char_t) '~') /* tilde */ +#define LIT_CHAR_QUESTION ((ecma_char_t) '?') /* question mark */ +#define LIT_CHAR_COLON ((ecma_char_t) ':') /* colon */ +#define LIT_CHAR_HASHMARK ((ecma_char_t) '#') /* hashmark */ + +/* + * Special characters for String.prototype.replace. + */ +#define LIT_CHAR_GRAVE_ACCENT ((ecma_char_t) '`') /* grave accent */ + +/** + * Uppercase ASCII letters + */ +#define LIT_CHAR_UPPERCASE_A ((ecma_char_t) 'A') +#define LIT_CHAR_UPPERCASE_B ((ecma_char_t) 'B') +#define LIT_CHAR_UPPERCASE_C ((ecma_char_t) 'C') +#define LIT_CHAR_UPPERCASE_D ((ecma_char_t) 'D') +#define LIT_CHAR_UPPERCASE_E ((ecma_char_t) 'E') +#define LIT_CHAR_UPPERCASE_F ((ecma_char_t) 'F') +#define LIT_CHAR_UPPERCASE_G ((ecma_char_t) 'G') +#define LIT_CHAR_UPPERCASE_H ((ecma_char_t) 'H') +#define LIT_CHAR_UPPERCASE_I ((ecma_char_t) 'I') +#define LIT_CHAR_UPPERCASE_J ((ecma_char_t) 'J') +#define LIT_CHAR_UPPERCASE_K ((ecma_char_t) 'K') +#define LIT_CHAR_UPPERCASE_L ((ecma_char_t) 'L') +#define LIT_CHAR_UPPERCASE_M ((ecma_char_t) 'M') +#define LIT_CHAR_UPPERCASE_N ((ecma_char_t) 'N') +#define LIT_CHAR_UPPERCASE_O ((ecma_char_t) 'O') +#define LIT_CHAR_UPPERCASE_P ((ecma_char_t) 'P') +#define LIT_CHAR_UPPERCASE_Q ((ecma_char_t) 'Q') +#define LIT_CHAR_UPPERCASE_R ((ecma_char_t) 'R') +#define LIT_CHAR_UPPERCASE_S ((ecma_char_t) 'S') +#define LIT_CHAR_UPPERCASE_T ((ecma_char_t) 'T') +#define LIT_CHAR_UPPERCASE_U ((ecma_char_t) 'U') +#define LIT_CHAR_UPPERCASE_V ((ecma_char_t) 'V') +#define LIT_CHAR_UPPERCASE_W ((ecma_char_t) 'W') +#define LIT_CHAR_UPPERCASE_X ((ecma_char_t) 'X') +#define LIT_CHAR_UPPERCASE_Y ((ecma_char_t) 'Y') +#define LIT_CHAR_UPPERCASE_Z ((ecma_char_t) 'Z') + +/** + * Lowercase ASCII letters + */ +#define LIT_CHAR_LOWERCASE_A ((ecma_char_t) 'a') +#define LIT_CHAR_LOWERCASE_B ((ecma_char_t) 'b') +#define LIT_CHAR_LOWERCASE_C ((ecma_char_t) 'c') +#define LIT_CHAR_LOWERCASE_D ((ecma_char_t) 'd') +#define LIT_CHAR_LOWERCASE_E ((ecma_char_t) 'e') +#define LIT_CHAR_LOWERCASE_F ((ecma_char_t) 'f') +#define LIT_CHAR_LOWERCASE_G ((ecma_char_t) 'g') +#define LIT_CHAR_LOWERCASE_H ((ecma_char_t) 'h') +#define LIT_CHAR_LOWERCASE_I ((ecma_char_t) 'i') +#define LIT_CHAR_LOWERCASE_J ((ecma_char_t) 'j') +#define LIT_CHAR_LOWERCASE_K ((ecma_char_t) 'k') +#define LIT_CHAR_LOWERCASE_L ((ecma_char_t) 'l') +#define LIT_CHAR_LOWERCASE_M ((ecma_char_t) 'm') +#define LIT_CHAR_LOWERCASE_N ((ecma_char_t) 'n') +#define LIT_CHAR_LOWERCASE_O ((ecma_char_t) 'o') +#define LIT_CHAR_LOWERCASE_P ((ecma_char_t) 'p') +#define LIT_CHAR_LOWERCASE_Q ((ecma_char_t) 'q') +#define LIT_CHAR_LOWERCASE_R ((ecma_char_t) 'r') +#define LIT_CHAR_LOWERCASE_S ((ecma_char_t) 's') +#define LIT_CHAR_LOWERCASE_T ((ecma_char_t) 't') +#define LIT_CHAR_LOWERCASE_U ((ecma_char_t) 'u') +#define LIT_CHAR_LOWERCASE_V ((ecma_char_t) 'v') +#define LIT_CHAR_LOWERCASE_W ((ecma_char_t) 'w') +#define LIT_CHAR_LOWERCASE_X ((ecma_char_t) 'x') +#define LIT_CHAR_LOWERCASE_Y ((ecma_char_t) 'y') +#define LIT_CHAR_LOWERCASE_Z ((ecma_char_t) 'z') + +/** + * ASCII decimal digits + */ +#define LIT_CHAR_0 ((ecma_char_t) '0') +#define LIT_CHAR_1 ((ecma_char_t) '1') +#define LIT_CHAR_2 ((ecma_char_t) '2') +#define LIT_CHAR_3 ((ecma_char_t) '3') +#define LIT_CHAR_4 ((ecma_char_t) '4') +#define LIT_CHAR_5 ((ecma_char_t) '5') +#define LIT_CHAR_6 ((ecma_char_t) '6') +#define LIT_CHAR_7 ((ecma_char_t) '7') +#define LIT_CHAR_8 ((ecma_char_t) '8') +#define LIT_CHAR_9 ((ecma_char_t) '9') + +/** + * ASCII character ranges + */ +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN LIT_CHAR_UPPERCASE_A /* uppercase letters range */ +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_END LIT_CHAR_UPPERCASE_Z + +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN LIT_CHAR_LOWERCASE_A /* lowercase letters range */ +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_END LIT_CHAR_LOWERCASE_Z + +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_HEX_BEGIN \ + LIT_CHAR_UPPERCASE_A /* uppercase letters for \ + * hexadecimal digits range */ +#define LIT_CHAR_ASCII_UPPERCASE_LETTERS_HEX_END LIT_CHAR_UPPERCASE_F + +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_BEGIN \ + LIT_CHAR_LOWERCASE_A /* lowercase letters for \ + * hexadecimal digits range */ +#define LIT_CHAR_ASCII_LOWERCASE_LETTERS_HEX_END LIT_CHAR_LOWERCASE_F + +#define LIT_CHAR_ASCII_OCTAL_DIGITS_BEGIN LIT_CHAR_0 /* octal digits range */ +#define LIT_CHAR_ASCII_OCTAL_DIGITS_END LIT_CHAR_7 + +#define LIT_CHAR_ASCII_DIGITS_BEGIN LIT_CHAR_0 /* decimal digits range */ +#define LIT_CHAR_ASCII_DIGITS_END LIT_CHAR_9 + +#define LEXER_TO_ASCII_LOWERCASE(character) ((character) | LIT_CHAR_SP) + +bool lit_char_is_octal_digit (ecma_char_t c); +bool lit_char_is_decimal_digit (ecma_char_t c); +bool lit_char_is_hex_digit (ecma_char_t c); +bool lit_char_is_binary_digit (ecma_char_t c); +uint8_t lit_char_to_radix (lit_utf8_byte_t c); +void lit_char_unicode_escape (ecma_stringbuilder_t *builder_p, ecma_char_t c); +uint32_t lit_char_hex_to_int (ecma_char_t c); +size_t lit_code_point_to_cesu8_bytes (uint8_t *dst_p, lit_code_point_t code_point); +size_t lit_code_point_get_cesu8_length (lit_code_point_t code_point); +void lit_four_byte_utf8_char_to_cesu8 (uint8_t *dst_p, const uint8_t *source_p); +uint32_t lit_char_hex_lookup (const lit_utf8_byte_t *buf_p, const lit_utf8_byte_t *const buf_end_p, uint32_t lookup); +uint32_t lit_parse_decimal (const lit_utf8_byte_t **buffer_p, const lit_utf8_byte_t *const buffer_end_p); +bool lit_find_char_in_string (ecma_string_t *str_p, lit_utf8_byte_t c); + +/** + * Null character + */ +#define LIT_CHAR_NULL ((ecma_char_t) '\0') + +/* + * Part of IsWordChar abstract operation (ECMA-262 v5, 15.10.2.6, step 3) + */ +bool lit_char_is_word_char (lit_code_point_t c); + +/* + * Utility functions for uppercasing / lowercasing + */ + +lit_code_point_t lit_char_to_lower_case (lit_code_point_t cp, ecma_stringbuilder_t *builder_p); +lit_code_point_t lit_char_to_upper_case (lit_code_point_t cp, ecma_stringbuilder_t *builder_p); + +bool lit_char_fold_to_lower (lit_code_point_t cp); +bool lit_char_fold_to_upper (lit_code_point_t cp); + +#endif /* !LIT_CHAR_HELPERS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-globals.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-globals.h new file mode 100644 index 00000000..a970eee1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-globals.h @@ -0,0 +1,121 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_GLOBALS_H +#define LIT_GLOBALS_H + +#include "jrt.h" + +/** + * ECMAScript standard defines terms "code unit" and "character" as 16-bit unsigned value + * used to represent 16-bit unit of text, this is the same as code unit in UTF-16 (See ECMA-262 5.1 Chapter 6). + * + * The term "code point" or "Unicode character" is used to refer a single Unicode scalar value (may be longer + * than 16 bits: 0x0 - 0x10FFFFF). One code point could be represented with one ore two 16-bit code units. + * + * According to the standard all strings and source text are assumed to be a sequence of code units. + * Length of a string equals to number of code units in the string, which is not the same as number of Unicode + * characters in a string. + * + * Internally JerryScript engine uses UTF-8 representation of strings to reduce memory overhead. Unicode character + * occupies from one to four bytes in UTF-8 representation. + * + * Unicode scalar value | Bytes in UTF-8 | Bytes in UTF-16 + * | (internal representation) | + * ---------------------------------------------------------------------- + * 0x0 - 0x7F | 1 byte | 2 bytes + * 0x80 - 0x7FF | 2 bytes | 2 bytes + * 0x800 - 0xFFFF | 3 bytes | 2 bytes + * 0x10000 - 0x10FFFF | 4 bytes | 4 bytes + * + * Scalar values from 0xD800 to 0xDFFF are permanently reserved by Unicode standard to encode high and low + * surrogates in UTF-16 (Code points 0x10000 - 0x10FFFF are encoded via pair of surrogates in UTF-16). + * Despite that the official Unicode standard says that no UTF forms can encode these code points, we allow + * them to be encoded inside strings. The reason for that is compatibility with ECMA standard. + * + * For example, assume a string which consists one Unicode character: 0x1D700 (Mathematical Italic Small Epsilon). + * It has the following representation in UTF-16: 0xD835 0xDF00. + * + * ECMA standard allows extracting a substring from this string: + * > var str = String.fromCharCode (0xD835, 0xDF00); // Create a string containing one character: 0x1D700 + * > str.length; // 2 + * > var str1 = str.substring (0, 1); + * > str1.length; // 1 + * > str1.charCodeAt (0); // 55349 (this equals to 0xD835) + * + * Internally original string would be represented in UTF-8 as the following byte sequence: 0xF0 0x9D 0x9C 0x80. + * After substring extraction high surrogate 0xD835 should be encoded via UTF-8: 0xED 0xA0 0xB5. + * + * Pair of low and high surrogates encoded separately should never occur in internal string representation, + * it should be encoded as any code point and occupy 4 bytes. So, when constructing a string from two surrogates, + * it should be processed gracefully; + * > var str1 = String.fromCharCode (0xD835); // 0xED 0xA0 0xB5 - internal representation + * > var str2 = String.fromCharCode (0xDF00); // 0xED 0xBC 0x80 - internal representation + * > var str = str1 + str2; // 0xF0 0x9D 0x9C 0x80 - internal representation, + * // !!! not 0xED 0xA0 0xB5 0xED 0xBC 0x80 + */ + +/** + * Description of an ecma-character, which represents 16-bit code unit, + * which is equal to UTF-16 character (see Chapter 6 from ECMA-262 5.1) + */ +typedef uint16_t ecma_char_t; + +/** + * Max bytes needed to represent a code unit (utf-16 char) via utf-8 encoding + */ +#define LIT_UTF8_MAX_BYTES_IN_CODE_UNIT (3) + +/** + * Max bytes needed to represent a code point (Unicode character) via utf-8 encoding + */ +#define LIT_UTF8_MAX_BYTES_IN_CODE_POINT (4) + +/** + * Max bytes needed to represent a code unit (utf-16 char) via cesu-8 encoding + */ +#define LIT_CESU8_MAX_BYTES_IN_CODE_UNIT (3) + +/** + * Max bytes needed to represent a code point (Unicode character) via cesu-8 encoding + */ +#define LIT_CESU8_MAX_BYTES_IN_CODE_POINT (6) + +/** + * A byte of utf-8 string + */ +typedef uint8_t lit_utf8_byte_t; + +/** + * Size of a utf-8 string in bytes + */ +typedef uint32_t lit_utf8_size_t; + +/** + * Size of a magic string in bytes + */ +typedef uint8_t lit_magic_size_t; + +/** + * Unicode code point + */ +typedef uint32_t lit_code_point_t; + +/** + * ECMA string hash + */ +typedef uint32_t lit_string_hash_t; + +#endif /* !LIT_GLOBALS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.cpp b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.cpp new file mode 100644 index 00000000..cc2b09de --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.cpp @@ -0,0 +1,432 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerry-config.h" +#include "lit-magic-strings.h" + +#include "jcontext.h" +#include "lit-strings.h" + +/** + * Maximum number of external magic strings that can be registered. + */ +#define LIT_EXTERNAL_MAGIC_STRING_LIMIT (UINT32_MAX / 2) + +/** + * Get number of external magic strings + * + * @return number of the strings, if there were registered, + * zero - otherwise. + */ +uint32_t +lit_get_magic_string_ex_count (void) +{ + return JERRY_CONTEXT (lit_magic_string_ex_count); +} /* lit_get_magic_string_ex_count */ + +/** + * Get specified magic string as zero-terminated string + * + * @return pointer to zero-terminated magic string + */ +const lit_utf8_byte_t * +lit_get_magic_string_utf8 (uint32_t id) /**< magic string id */ +{ + static const lit_utf8_byte_t *const lit_magic_strings[] JERRY_ATTR_CONST_DATA = { +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) +#define LIT_MAGIC_STRING_DEF(id, utf8_string) (const lit_utf8_byte_t *) utf8_string, +#include "lit-magic-strings.inc.h" +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + }; + + JERRY_ASSERT (id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT); + + return lit_magic_strings[id]; +} /* lit_get_magic_string_utf8 */ + +/** + * Get size of specified magic string + * + * @return size in bytes + */ +lit_utf8_size_t +lit_get_magic_string_size (uint32_t id) /**< magic string id */ +{ + static const lit_magic_size_t lit_magic_string_sizes[] JERRY_ATTR_CONST_DATA = { +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) +#define LIT_MAGIC_STRING_DEF(id, utf8_string) sizeof (utf8_string) - 1, +#include "lit-magic-strings.inc.h" +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + }; + + JERRY_ASSERT (id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT); + + return lit_magic_string_sizes[id]; +} /* lit_get_magic_string_size */ + +/** + * Get the block start element with the given size from + * the list of ECMA and implementation-defined magic string constants + * + * @return magic string id + */ +static lit_magic_string_id_t +lit_get_magic_string_size_block_start (lit_utf8_size_t size) /**< magic string size */ +{ + static const lit_magic_string_id_t lit_magic_string_size_block_starts[] JERRY_ATTR_CONST_DATA = { +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_DEF(id, utf8_string) +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) id, +#include "lit-magic-strings.inc.h" + LIT_NON_INTERNAL_MAGIC_STRING__COUNT +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + }; + + JERRY_ASSERT (size <= (sizeof (lit_magic_string_size_block_starts) / sizeof (lit_magic_string_id_t))); + + return lit_magic_string_size_block_starts[size]; +} /* lit_get_magic_string_size_block_start */ + +/** + * Get specified magic string as zero-terminated string from external table + * + * @return pointer to zero-terminated magic string + */ +const lit_utf8_byte_t * +lit_get_magic_string_ex_utf8 (uint32_t id) /**< extern magic string id */ +{ + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_array) && id < JERRY_CONTEXT (lit_magic_string_ex_count)); + + return JERRY_CONTEXT (lit_magic_string_ex_array)[id]; +} /* lit_get_magic_string_ex_utf8 */ + +/** + * Get size of specified external magic string + * + * @return size in bytes + */ +lit_utf8_size_t +lit_get_magic_string_ex_size (uint32_t id) /**< external magic string id */ +{ + return JERRY_CONTEXT (lit_magic_string_ex_sizes)[id]; +} /* lit_get_magic_string_ex_size */ + +/** + * Register external magic strings + */ +void +lit_magic_strings_ex_set (const lit_utf8_byte_t *const *ex_str_items, /**< character arrays, representing + * external magic strings' contents */ + uint32_t count, /**< number of the strings */ + const lit_utf8_size_t *ex_str_sizes) /**< sizes of the strings */ +{ + JERRY_ASSERT (ex_str_items != NULL); + JERRY_ASSERT (count > 0); + JERRY_ASSERT (ex_str_sizes != NULL); + + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_array) == NULL); + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_count) == 0); + JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_sizes) == NULL); + + /* Limit the number of external magic strings */ + if (count > LIT_EXTERNAL_MAGIC_STRING_LIMIT) + { + count = LIT_EXTERNAL_MAGIC_STRING_LIMIT; + } + + /* Set external magic strings information */ + JERRY_CONTEXT (lit_magic_string_ex_array) = ex_str_items; + JERRY_CONTEXT (lit_magic_string_ex_count) = count; + JERRY_CONTEXT (lit_magic_string_ex_sizes) = ex_str_sizes; + +#ifndef JERRY_NDEBUG + for (lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) 0; id < JERRY_CONTEXT (lit_magic_string_ex_count); + id = (lit_magic_string_ex_id_t) (id + 1)) + { + lit_utf8_size_t string_size = JERRY_CONTEXT (lit_magic_string_ex_sizes)[id]; + + /** + * Check whether the strings are sorted by size and lexicographically, + * e.g., "Bb" < "aa" < "aaa" < "xyz0". + */ + if (id > 0) + { + const lit_magic_string_ex_id_t prev_id = id - 1; + const lit_utf8_size_t prev_string_size = lit_get_magic_string_ex_size (prev_id); + JERRY_ASSERT (lit_is_valid_cesu8_string (lit_get_magic_string_ex_utf8 (id), string_size)); + JERRY_ASSERT (prev_string_size <= string_size); + + if (prev_string_size == string_size) + { + const lit_utf8_byte_t *prev_ex_string_p = lit_get_magic_string_ex_utf8 (prev_id); + const lit_utf8_byte_t *curr_ex_string_p = lit_get_magic_string_ex_utf8 (id); + JERRY_ASSERT (memcmp (prev_ex_string_p, curr_ex_string_p, string_size) < 0); + } + } + } +#endif /* !JERRY_NDEBUG */ +} /* lit_magic_strings_ex_set */ + +/** + * Returns the magic string id of the argument string if it is available. + * + * @return id - if magic string id is found, + * LIT_MAGIC_STRING__COUNT - otherwise. + */ +lit_magic_string_id_t +lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< string size in bytes */ +{ + if (string_size > lit_get_magic_string_size (LIT_NON_INTERNAL_MAGIC_STRING__COUNT - 1)) + { + return LIT_MAGIC_STRING__COUNT; + } + + /**< The string must be in this id range. */ + lit_utf8_size_t first = lit_get_magic_string_size_block_start (string_size); + lit_utf8_size_t last = lit_get_magic_string_size_block_start (string_size + 1); + + while (first < last) + { + lit_utf8_size_t middle = ((first + last) / 2); /**< mid point of search */ + int compare = memcmp (lit_get_magic_string_utf8 ((lit_magic_string_id_t) middle), string_p, string_size); + + if (compare == 0) + { + return (lit_magic_string_id_t) middle; + } + else if (compare > 0) + { + last = middle; + } + else + { + first = middle + 1; + } + } + + return LIT_MAGIC_STRING__COUNT; +} /* lit_is_utf8_string_magic */ + +/** + * Returns the magic string id of the argument string pair if it is available. + * + * @return id - if magic string id is found, + * LIT_MAGIC_STRING__COUNT - otherwise. + */ +lit_magic_string_id_t +lit_is_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ + lit_utf8_size_t string1_size, /**< first string size in bytes */ + const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ + lit_utf8_size_t string2_size) /**< second string size in bytes */ +{ + lit_utf8_size_t total_string_size = string1_size + string2_size; + + if (total_string_size > lit_get_magic_string_size (LIT_NON_INTERNAL_MAGIC_STRING__COUNT - 1)) + { + return LIT_MAGIC_STRING__COUNT; + } + + /**< The string must be in this id range. */ + lit_utf8_size_t first = lit_get_magic_string_size_block_start (total_string_size); + lit_utf8_size_t last = lit_get_magic_string_size_block_start (total_string_size + 1); + + while (first < last) + { + lit_utf8_size_t middle = ((first + last) / 2); /**< mid point of search */ + const lit_utf8_byte_t *middle_string_p = lit_get_magic_string_utf8 ((lit_magic_string_id_t) middle); + + int compare = memcmp (middle_string_p, string1_p, string1_size); + + if (compare == 0) + { + compare = memcmp (middle_string_p + string1_size, string2_p, string2_size); + } + + if (compare == 0) + { + return (lit_magic_string_id_t) middle; + } + else if (compare > 0) + { + last = middle; + } + else + { + first = middle + 1; + } + } + + return LIT_MAGIC_STRING__COUNT; +} /* lit_is_utf8_string_pair_magic */ + +/** + * Returns the ex magic string id of the argument string if it is available. + * + * @return id - if magic string id is found, + * lit_get_magic_string_ex_count () - otherwise. + */ +lit_magic_string_ex_id_t +lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< string size in bytes */ +{ + const uint32_t magic_string_ex_count = lit_get_magic_string_ex_count (); + + if (magic_string_ex_count == 0 || string_size > lit_get_magic_string_ex_size (magic_string_ex_count - 1)) + { + return (lit_magic_string_ex_id_t) magic_string_ex_count; + } + + lit_magic_string_ex_id_t first = 0; + lit_magic_string_ex_id_t last = (lit_magic_string_ex_id_t) magic_string_ex_count; + + while (first < last) + { + const lit_magic_string_ex_id_t middle = (first + last) / 2; + const lit_utf8_byte_t *ext_string_p = lit_get_magic_string_ex_utf8 (middle); + const lit_utf8_size_t ext_string_size = lit_get_magic_string_ex_size (middle); + + if (string_size == ext_string_size) + { + const int string_compare = memcmp (ext_string_p, string_p, string_size); + + if (string_compare == 0) + { + return middle; + } + else if (string_compare < 0) + { + first = middle + 1; + } + else + { + last = middle; + } + } + else if (string_size > ext_string_size) + { + first = middle + 1; + } + else + { + last = middle; + } + } + + return (lit_magic_string_ex_id_t) magic_string_ex_count; +} /* lit_is_ex_utf8_string_magic */ + +/** + * Returns the ex magic string id of the argument string pair if it is available. + * + * @return id - if magic string id is found, + * lit_get_magic_string_ex_count () - otherwise. + */ +lit_magic_string_ex_id_t +lit_is_ex_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ + lit_utf8_size_t string1_size, /**< first string size in bytes */ + const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ + lit_utf8_size_t string2_size) /**< second string size in bytes */ +{ + const uint32_t magic_string_ex_count = lit_get_magic_string_ex_count (); + const lit_utf8_size_t total_string_size = string1_size + string2_size; + + if (magic_string_ex_count == 0 || total_string_size > lit_get_magic_string_ex_size (magic_string_ex_count - 1)) + { + return (lit_magic_string_ex_id_t) magic_string_ex_count; + } + + lit_magic_string_ex_id_t first = 0; + lit_magic_string_ex_id_t last = (lit_magic_string_ex_id_t) magic_string_ex_count; + + while (first < last) + { + const lit_magic_string_ex_id_t middle = (first + last) / 2; + const lit_utf8_byte_t *ext_string_p = lit_get_magic_string_ex_utf8 (middle); + const lit_utf8_size_t ext_string_size = lit_get_magic_string_ex_size (middle); + + if (total_string_size == ext_string_size) + { + int string_compare = memcmp (ext_string_p, string1_p, string1_size); + + if (string_compare == 0) + { + string_compare = memcmp (ext_string_p + string1_size, string2_p, string2_size); + } + + if (string_compare == 0) + { + return middle; + } + else if (string_compare < 0) + { + first = middle + 1; + } + else + { + last = middle; + } + } + else if (total_string_size > ext_string_size) + { + first = middle + 1; + } + else + { + last = middle; + } + } + + return (lit_magic_string_ex_id_t) magic_string_ex_count; +} /* lit_is_ex_utf8_string_pair_magic */ + +/** + * Copy magic string to buffer + * + * Warning: + * the routine requires that buffer size is enough + * + * @return pointer to the byte next to the last copied in the buffer + */ +lit_utf8_byte_t * +lit_copy_magic_string_to_buffer (lit_magic_string_id_t id, /**< magic string id */ + lit_utf8_byte_t *buffer_p, /**< destination buffer */ + lit_utf8_size_t buffer_size) /**< size of buffer */ +{ + const lit_utf8_byte_t *magic_string_bytes_p = lit_get_magic_string_utf8 (id); + lit_utf8_size_t magic_string_bytes_count = lit_get_magic_string_size (id); + + const lit_utf8_byte_t *str_iter_p = magic_string_bytes_p; + lit_utf8_byte_t *buf_iter_p = buffer_p; + lit_utf8_size_t bytes_copied = 0; + + while (magic_string_bytes_count--) + { + bytes_copied++; + JERRY_ASSERT (bytes_copied <= buffer_size); + + *buf_iter_p++ = *str_iter_p++; + } + + return buf_iter_p; +} /* lit_copy_magic_string_to_buffer */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.h new file mode 100644 index 00000000..a079396c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.h @@ -0,0 +1,118 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_MAGIC_STRINGS_H +#define LIT_MAGIC_STRINGS_H + +#include "lit-globals.h" + +/** + * Identifiers of ECMA and implementation-defined magic string constants + */ +typedef enum +{ +/** @cond doxygen_suppress */ +#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) +#define LIT_MAGIC_STRING_DEF(id, ascii_zt_string) id, +#include "lit-magic-strings.inc.h" +#undef LIT_MAGIC_STRING_DEF +#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE + /** @endcond */ + LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< number of non-internal magic strings */ + LIT_INTERNAL_MAGIC_API_INTERNAL = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< Used to add non-visible JS properties + * from the public API */ + LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX, /**< [[%Iterator%NextIndex]] property */ + LIT_INTERNAL_MAGIC_STRING_MAP_KEY, /**< Property key used when an object is a key in a map object */ + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, /**< %ArrayProto_values% intrinsic routine */ + LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, /**< %TypedArray%.prototype values and [@@iterator] routine */ + LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, /**< Set.prototype values, keys and [@@iterator] routines */ + LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, /**< Map.prototype entries and [@@iterator] routines */ + /* List of well known symbols */ + LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well known symbol */ + LIT_GLOBAL_SYMBOL__FIRST = LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< first global symbol */ + LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well known symbol */ + LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well known symbol */ + LIT_GLOBAL_SYMBOL_ITERATOR, /**< @@iterator well known symbol */ + LIT_GLOBAL_SYMBOL_MATCH, /**< @@match well known symbol */ + LIT_GLOBAL_SYMBOL_REPLACE, /**< @@replace well known symbol */ + LIT_GLOBAL_SYMBOL_SEARCH, /**< @@search well known symbol */ + LIT_GLOBAL_SYMBOL_SPECIES, /**< @@species well known symbol */ + LIT_GLOBAL_SYMBOL_SPLIT, /**< @@split well known symbol */ + LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, /**< @@toPrimitive well known symbol */ + LIT_GLOBAL_SYMBOL_TO_STRING_TAG, /**< @@toStringTag well known symbol */ + LIT_GLOBAL_SYMBOL_UNSCOPABLES, /**< @@unscopables well known symbol */ + LIT_GLOBAL_SYMBOL_MATCH_ALL, /**< @@matchAll well known symbol */ + LIT_GLOBAL_SYMBOL__LAST = LIT_GLOBAL_SYMBOL_MATCH_ALL, /**< last global symbol */ + + LIT_INTERNAL_MAGIC_STRING_DELETED, /**< special value for deleted properties */ + LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT, /**< function which initializes properties */ + + LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< native pointer info associated with an object */ + LIT_INTERNAL_MAGIC_STRING_FIRST_DATA = LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< first index of special + * data properties */ + LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER_WITH_REFERENCES, /**< native pointer info associated with an object + * which contains references to other values */ + LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD, /**< dynamic environment record needed by class constructors */ + LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED, /**< computed class field name list */ + LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS, /**< internal collection for storing private elements */ + LIT_INTERNAL_MAGIC_STRING_CONTAINER_WEAK_REFS, /**< Weak references to the current container object */ + LIT_INTERNAL_MAGIC_STRING_WEAK_REFS, /**< Weak references to the current object */ + LIT_MAGIC_STRING__COUNT /**< number of magic strings */ +} lit_magic_string_id_t; + +/** + * Properties that are need to be ignored for opfunc_set_class_attributes + */ +#define LIT_INTERNAL_MAGIC_STRING_IGNORED(id) \ + ((id) >= LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED && (id) <= LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS) + +/** + * Checks whether the given id corresponds to a global symbol + */ +#define LIT_IS_GLOBAL_SYMBOL(id) ((id) >= LIT_GLOBAL_SYMBOL__FIRST && (id) <= LIT_GLOBAL_SYMBOL__LAST) + +/** + * Identifiers of implementation-defined external magic string constants + */ +typedef uint32_t lit_magic_string_ex_id_t; + +uint32_t lit_get_magic_string_ex_count (void); + +const lit_utf8_byte_t *lit_get_magic_string_utf8 (uint32_t id); +lit_utf8_size_t lit_get_magic_string_size (uint32_t id); + +const lit_utf8_byte_t *lit_get_magic_string_ex_utf8 (uint32_t id); +lit_utf8_size_t lit_get_magic_string_ex_size (uint32_t id); + +void lit_magic_strings_ex_set (const lit_utf8_byte_t *const *ex_str_items, + uint32_t count, + const lit_utf8_size_t *ex_str_sizes); + +lit_magic_string_id_t lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +lit_magic_string_id_t lit_is_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, + lit_utf8_size_t string1_size, + const lit_utf8_byte_t *string2_p, + lit_utf8_size_t string2_size); + +lit_magic_string_ex_id_t lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); +lit_magic_string_ex_id_t lit_is_ex_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, + lit_utf8_size_t string1_size, + const lit_utf8_byte_t *string2_p, + lit_utf8_size_t string2_size); + +lit_utf8_byte_t * +lit_copy_magic_string_to_buffer (lit_magic_string_id_t id, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); + +#endif /* !LIT_MAGIC_STRINGS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.inc.h new file mode 100644 index 00000000..2d1519c7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-magic-strings.inc.h @@ -0,0 +1,985 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-strings.py script + * from lit-magic-strings.ini. Do not edit! */ + +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__EMPTY, "") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPACE_CHAR, " ") +#if JERRY_MODULE_SYSTEM +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASTERIX_CHAR, "*") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_E_U, "E") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, "[") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR, "]") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PI_U, "PI") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_AT, "at") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS, "is") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OF, "of") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_OR, "or") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LN2_U, "LN2") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAP_UL, "Map") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NAN, "NaN") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UL, "Set") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UTC_U, "UTC") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ABS, "abs") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ADD, "add") +#endif /* JERRY_BUILTIN_ATOMICS \ +|| JERRY_BUILTIN_CONTAINER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ALL, "all") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_AND, "and") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ANY, "any") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COS, "cos") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXP, "exp") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FOR, "for") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET, "get") +#if JERRY_BUILTIN_CONTAINER || JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS, "has") +#endif /* JERRY_BUILTIN_CONTAINER \ +|| JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG, "log") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAP, "map") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAX, "max") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN, "min") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NOW, "now") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POP, "pop") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POW, "pow") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RAW, "raw") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET, "set") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIN, "sin") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_SUB, "sub") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TAN, "tan") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_XOR, "xor") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP, "(?:)") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DATE_UL, "Date") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LN10_U, "LN10") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MATH_UL, "Math") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NULL_UL, "Null") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ACOS, "acos") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASIN, "asin") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATAN, "atan") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIND, "bind") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALL, "call") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CBRT, "cbrt") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CEIL, "ceil") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COSH, "cosh") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DONE, "done") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVAL, "eval") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXEC, "exec") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FILL, "fill") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FIND, "find") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLAT, "flat") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROM, "from") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IMUL, "imul") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_JOIN, "join") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_KEYS, "keys") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_LOAD, "load") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG2, "log2") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NAME, "name") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEXT, "next") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NULL, "null") +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PUSH, "push") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RACE, "race") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SEAL, "seal") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIGN, "sign") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SINH, "sinh") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIZE, "size") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOME, "some") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SORT, "sort") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT, "sqrt") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TANH, "tanh") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TEST, "test") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_THEN, "then") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM, "trim") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRUE, "true") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_WAIT, "wait") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_UL, "Array") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ERROR_UL, "Error") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG2E_U, "LOG2E") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROXY_UL, "Proxy") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT2_U, "SQRT2") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ACOSH, "acosh") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_APPLY, "apply") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASINH, "asinh") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATAN2, "atan2") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATANH, "atanh") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CATCH, "catch") +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CLEAR, "clear") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CLZ32, "clz32") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_WEAKREF +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEREF, "deref") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVERY, "every") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXPM1, "expm1") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FALSE, "false") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLAGS, "flags") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLOOR, "floor") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HYPOT, "hypot") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INDEX, "index") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INPUT, "input") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_NAN, "isNaN") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG10, "log10") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG1P, "log1p") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MATCH, "match") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE, "parse") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROXY, "proxy") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ROUND, "round") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SHIFT, "shift") +#endif /* JERRY_BUILTIN_ARRAY */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_SHAREDARRAYBUFFER || JERRY_BUILTIN_STRING || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLICE, "slice") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_SHAREDARRAYBUFFER \ +|| JERRY_BUILTIN_STRING \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPLIT, "split") +#if JERRY_LINE_INFO +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STACK, "stack") +#endif /* JERRY_LINE_INFO */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_STORE, "store") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_THROW, "throw") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRUNC, "trunc") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE, "value") +#if JERRY_PARSER && JERRY_SOURCE_NAME +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOURCE_NAME_EVAL, "") +#endif /* JERRY_PARSER && JERRY_SOURCE_NAME */ +#if JERRY_BUILTIN_BIGINT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT_UL, "BigInt") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG10E_U, "LOG10E") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_MODULE_SYSTEM +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MODULE_UL, "Module") +#endif /* JERRY_MODULE_SYSTEM */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NUMBER_UL, "Number") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_UL, "Object") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REGEXP_UL, "RegExp") +#if JERRY_PARSER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SCRIPT_UL, "Script") +#endif /* JERRY_PARSER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING_UL, "String") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_UL, "Symbol") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASSIGN, "assign") +#if JERRY_BUILTIN_BIGINT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT, "bigint") +#endif /* JERRY_BUILTIN_BIGINT */ +#if JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BUFFER, "buffer") +#endif /* JERRY_BUILTIN_DATAVIEW \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALLEE, "callee") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALLER, "caller") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CHAR_AT_UL, "charAt") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONCAT, "concat") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CREATE, "create") +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DELETE, "delete") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DOTALL, "dotAll") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ERRORS_UL, "errors") +#if JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ESCAPE, "escape") +#endif /* JERRY_BUILTIN_ANNEXB */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FILTER, "filter") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FREEZE, "freeze") +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROUND, "fround") +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_DAY_UL, "getDay") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GLOBAL, "global") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_OWN_UL, "hasOwn") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_VIEW_UL, "isView") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_KEY_FOR, "keyFor") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LENGTH, "length") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_NOTIFY, "notify") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NUMBER, "number") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT, "object") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PAD_END, "padEnd") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RANDOM, "random") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REASON, "reason") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REDUCE, "reduce") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REJECT, "reject") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPEAT, "repeat") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RETURN, "return") +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVOKE, "revoke") +#endif /* JERRY_BUILTIN_PROXY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SEARCH, "search") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOURCE, "source") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPLICE, "splice") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STATUS, "status") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STICKY, "sticky") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING, "string") +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBSTR, "substr") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL, "symbol") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_JSON_UL, "toJSON") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUES, "values") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_U, "Atomics") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN_UL, "Boolean") +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EPSILON_U, "EPSILON") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROMISE_UL, "Promise") +#if JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REFLECT_UL, "Reflect") +#endif /* JERRY_BUILTIN_REFLECT */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT1_2_U, "SQRT1_2") +#endif /* JERRY_BUILTIN_MATH */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_DOT_UL, "Symbol.") +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WEAKMAP_UL, "WeakMap") +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_WEAKREF +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WEAKREF_UL, "WeakRef") +#endif /* JERRY_BUILTIN_WEAKREF */ +#if JERRY_BUILTIN_CONTAINER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WEAKSET_UL, "WeakSet") +#endif /* JERRY_BUILTIN_CONTAINER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN, "boolean") +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFAULT, "default") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENTRIES, "entries") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FINALLY, "finally") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLATMAP, "flatMap") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_CONTAINER || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FOR_EACH_UL, "forEach") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_CONTAINER \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_DATE_UL, "getDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT8_UL, "getInt8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_TIME_UL, "getTime") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_YEAR_UL, "getYear") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_STRING || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INDEX_OF_UL, "indexOf") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_STRING \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_ARRAY_UL, "isArray") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MESSAGE, "message") +#if JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OWN_KEYS_UL, "ownKeys") +#endif /* JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPLACE, "replace") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RESOLVE, "resolve") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVERSE, "reverse") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_DATE_UL, "setDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT8_UL, "setInt8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_TIME_UL, "setTime") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_YEAR_UL, "setYear") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPECIES, "species") +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_FIXED_UL, "toFixed") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_END, "trimEnd") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNICODE, "unicode") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNSHIFT, "unshift") +#endif /* JERRY_BUILTIN_ARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE_OF_UL, "valueOf") +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DATAVIEW_UL, "DataView") +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_UL, "Function") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INFINITY_UL, "Infinity") +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_URI_ERROR_UL, "URIError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_TO_STRING_UL, "[object ") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENDS_WITH, "endsWith") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_EXCHANGE, "exchange") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION, "function") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_HOURS_UL, "getHours") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT16_UL, "getInt16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT32_UL, "getInt32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MONTH_UL, "getMonth") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT8_UL, "getUint8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INCLUDES, "includes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FINITE, "isFinite") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FROZEN_UL, "isFrozen") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SEALED_UL, "isSealed") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ITERATOR, "iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MATCH_ALL, "matchAll") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PAD_START, "padStart") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_INT, "parseInt") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REJECTED, "rejected") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_HOURS_UL, "setHours") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT16_UL, "setInt16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT32_UL, "setInt32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MONTH_UL, "setMonth") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT8_UL, "setUint8") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBARRAY, "subarray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_STRING_UL, "toString") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_LEFT, "trimLeft") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNESCAPE, "unescape") +#endif /* JERRY_BUILTIN_ANNEXB */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_WRITABLE, "writable") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL, "-Infinity") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARGUMENTS_UL, "Arguments") +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVAL_ERROR_UL, "EvalError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GENERATOR_UL, "Generator") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INT8_ARRAY_UL, "Int8Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAX_VALUE_U, "MAX_VALUE") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN_VALUE_U, "MIN_VALUE") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TYPE_ERROR_UL, "TypeError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNDEFINED_UL, "Undefined") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__PROTO__, "__proto__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ANONYMOUS, "anonymous") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARGUMENTS, "arguments") +#if JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONSTRUCT, "construct") +#endif /* JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DECODE_URI, "decodeURI") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENCODE_URI, "encodeURI") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FIND_INDEX, "findIndex") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FULFILLED, "fulfilled") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DAY_UL, "getUTCDay") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT16_UL, "getUint16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT32_UL, "getUint32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_INTEGER, "isInteger") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LASTINDEX_UL, "lastIndex") +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MULTILINE, "multiline") +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROTOTYPE, "prototype") +#if JERRY_BUILTIN_PROXY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVOCABLE, "revocable") +#endif /* JERRY_BUILTIN_PROXY */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT16_UL, "setUint16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT32_UL, "setUint32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBSTRING, "substring") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_RIGHT, "trimRight") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_START, "trimStart") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNDEFINED, "undefined") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INT16_ARRAY_UL, "Int16Array") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INT32_ARRAY_UL, "Int32Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RANGE_ERROR_UL, "RangeError") +#endif /* JERRY_BUILTIN_ERRORS */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TYPED_ARRAY_UL, "TypedArray") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT8_ARRAY_UL, "Uint8Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ALLSETTLED, "allSettled") +#if JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_SHAREDARRAYBUFFER || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_LENGTH_UL, "byteLength") +#endif /* JERRY_BUILTIN_DATAVIEW \ +|| JERRY_BUILTIN_SHAREDARRAYBUFFER \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_OFFSET_UL, "byteOffset") +#endif /* JERRY_BUILTIN_DATAVIEW \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, "charCodeAt") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COPY_WITHIN, "copyWithin") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENUMERABLE, "enumerable") +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FLOAT_32_UL, "getFloat32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FLOAT_64_UL, "getFloat64") +#endif /* JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MINUTES_UL, "getMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_SECONDS_UL, "getSeconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DATE_UL, "getUTCDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_GLOBAL_THIS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GLOBAL_THIS_UL, "globalThis") +#endif /* JERRY_BUILTIN_GLOBAL_THIS */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IGNORECASE_UL, "ignoreCase") +#endif /* JERRY_BUILTIN_REGEXP */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_ISLOCKFREE, "isLockFree") +#endif /* JERRY_BUILTIN_ATOMICS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_FLOAT, "parseFloat") +#if JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPLACE_ALL, "replaceAll") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FLOAT_32_UL, "setFloat32") +#endif /* JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FLOAT_64_UL, "setFloat64") +#endif /* JERRY_BUILTIN_DATAVIEW && JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MINUTES_UL, "setMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_SECONDS_UL, "setSeconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_DATE_UL, "setUTCDate") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STARTS_WITH, "startsWith") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOURCE_NAME_ANON, "") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_BUFFER_UL, "ArrayBuffer") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYNTAX_ERROR_UL, "SyntaxError") +#endif /* JERRY_BUILTIN_ERRORS */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT16_ARRAY_UL, "Uint16Array") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT32_ARRAY_UL, "Uint32Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CODE_POINT_AT, "codePointAt") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONSTRUCTOR, "constructor") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DESCRIPTION, "description") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_FROM_ENTRIES, "fromEntries") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_BIGINT64, "getBigInt64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FULL_YEAR_UL, "getFullYear") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_HOURS_UL, "getUTCHours") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MONTH_UL, "getUTCMonth") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_INSTANCE, "hasInstance") +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_STRING || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, "lastIndexOf") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_STRING \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, "reduceRight") +#endif /* JERRY_BUILTIN_ARRAY \ +|| JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_BIGINT64, "setBigInt64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FULL_YEAR_UL, "setFullYear") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_HOURS_UL, "setUTCHours") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MONTH_UL, "setUTCMonth") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_GMT_STRING_UL, "toGMTString") +#endif /* JERRY_BUILTIN_ANNEXB && JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_ISO_STRING_UL, "toISOString") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOWER_CASE_UL, "toLowerCase") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_PRECISION_UL, "toPrecision") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_PRIMITIVE, "toPrimitive") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_STRING_TAG, "toStringTag") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_UTC_STRING_UL, "toUTCString") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_UPPER_CASE_UL, "toUpperCase") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNSCOPABLES, "unscopables") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLOAT32_ARRAY_UL, "Float32Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLOAT64_ARRAY_UL, "Float64Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INVALID_DATE_UL, "Invalid Date") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAP_ITERATOR_UL, "Map Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_ITERATOR_UL, "Set Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONFIGURABLE, "configurable") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROM_CHAR_CODE_UL, "fromCharCode") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_BIGUINT64, "getBigUint64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_EXTENSIBLE, "isExtensible") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_BIGUINT64, "setBigUint64") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_DATAVIEW */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_DATE_STRING_UL, "toDateString") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_TIME_STRING_UL, "toTimeString") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_FUNCTION_UL, "AsyncFunction") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT64_ARRAY_UL, "BigInt64Array") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_ITERATOR, "asyncIterator") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROM_CODE_POINT_UL, "fromCodePoint") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MINUTES_UL, "getUTCMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_SECONDS_UL, "getUTCSeconds") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL, "isPrototypeOf") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SAFE_INTEGER, "isSafeInteger") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOCALE_COMPARE_UL, "localeCompare") +#endif /* JERRY_BUILTIN_STRING */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MINUTES_UL, "setUTCMinutes") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_SECONDS_UL, "setUTCSeconds") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_EXPONENTIAL_UL, "toExponential") +#endif /* JERRY_BUILTIN_NUMBER */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_AGGREGATE_ERROR_UL, "AggregateError") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_ITERATOR_UL, "Array Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_GENERATOR_UL, "AsyncGenerator") +#if JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGUINT64_ARRAY_UL, "BigUint64Array") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REFERENCE_ERROR_UL, "ReferenceError") +#endif /* JERRY_BUILTIN_ERRORS */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, "defineProperty") +#if JERRY_BUILTIN_PROXY || JERRY_BUILTIN_REFLECT +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DELETE_PROPERTY_UL, "deleteProperty") +#endif /* JERRY_BUILTIN_PROXY \ +|| JERRY_BUILTIN_REFLECT */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, "getPrototypeOf") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_FULL_YEAR_UL, "getUTCFullYear") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL, "hasOwnProperty") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, "setPrototypeOf") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_FULL_YEAR_UL, "setUTCFullYear") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, "toLocaleString") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING_ITERATOR_UL, "String Iterator") +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATOMICS_COMPAREEXCHANGE, "compareExchange") +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MILLISECONDS_UL, "getMilliseconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MILLISECONDS_UL, "setMilliseconds") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MAX_SAFE_INTEGER_U, "MAX_SAFE_INTEGER") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN_SAFE_INTEGER_U, "MIN_SAFE_INTEGER") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_GETTER, "__defineGetter__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_SETTER, "__defineSetter__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOOKUP_GETTER, "__lookupGetter__") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOOKUP_SETTER, "__lookupSetter__") +#endif /* JERRY_BUILTIN_ANNEXB */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL, "defineProperties") +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U, "BYTES_PER_ELEMENT") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL, "GeneratorFunction") +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEGATIVE_INFINITY_U, "NEGATIVE_INFINITY") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POSITIVE_INFINITY_U, "POSITIVE_INFINITY") +#endif /* JERRY_BUILTIN_NUMBER */ +#if JERRY_BUILTIN_SHAREDARRAYBUFFER +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SHARED_ARRAY_BUFFER_UL, "SharedArrayBuffer") +#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL, "Uint8ClampedArray") +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_TIMEZONE_OFFSET_UL, "getTimezoneOffset") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL, "preventExtensions") +#if JERRY_BUILTIN_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_LOWER_CASE_UL, "toLocaleLowerCase") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_UPPER_CASE_UL, "toLocaleUpperCase") +#endif /* JERRY_BUILTIN_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, "decodeURIComponent") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, "encodeURIComponent") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MILLISECONDS_UL, "getUTCMilliseconds") +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, "isConcatSpreadable") +#if JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL, "setUTCMilliseconds") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL, "toLocaleDateString") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL, "toLocaleTimeString") +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON, "function anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, "getOwnPropertyNames") +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR, "function* anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, "propertyIsEnumerable") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL, "getOwnPropertySymbols") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL, "AsyncGeneratorFunction") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL, "RegExp String Iterator") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, "getOwnPropertyDescriptor") +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC, "async function anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL, "getOwnPropertyDescriptors") +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR, "async function* anonymous(") +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE, "function () { [native code] }") +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA, "function () { /* ecmascript */ }") +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ + +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (0, LIT_MAGIC_STRING__EMPTY) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (1, LIT_MAGIC_STRING_SPACE_CHAR) +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (2, LIT_MAGIC_STRING_PI_U) +#else /* !(JERRY_BUILTIN_MATH) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (2, LIT_MAGIC_STRING_AT) +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (3, LIT_MAGIC_STRING_LN2_U) +#else /* !(JERRY_BUILTIN_MATH) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (3, LIT_MAGIC_STRING_MAP_UL) +#endif /* JERRY_BUILTIN_MATH */ +#if JERRY_BUILTIN_REGEXP +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP) +#else /* !(JERRY_BUILTIN_REGEXP) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_DATE_UL) +#endif /* JERRY_BUILTIN_REGEXP */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (5, LIT_MAGIC_STRING_ARRAY_UL) +#if JERRY_PARSER && JERRY_SOURCE_NAME +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_SOURCE_NAME_EVAL) +#elif JERRY_BUILTIN_BIGINT +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_BIGINT_UL) +#elif JERRY_BUILTIN_MATH +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_LOG10E_U) +#elif JERRY_MODULE_SYSTEM +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_MODULE_UL) +#else /* !(JERRY_MODULE_SYSTEM) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_NUMBER_UL) +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_BUILTIN_ATOMICS +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (7, LIT_MAGIC_STRING_ATOMICS_U) +#else /* !(JERRY_BUILTIN_ATOMICS) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (7, LIT_MAGIC_STRING_BOOLEAN_UL) +#endif /* JERRY_BUILTIN_ATOMICS */ +#if JERRY_BUILTIN_DATAVIEW +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (8, LIT_MAGIC_STRING_DATAVIEW_UL) +#else /* !(JERRY_BUILTIN_DATAVIEW) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (8, LIT_MAGIC_STRING_FUNCTION_UL) +#endif /* JERRY_BUILTIN_DATAVIEW */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (9, LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL) +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_INT16_ARRAY_UL) +#elif JERRY_BUILTIN_ERRORS +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_RANGE_ERROR_UL) +#elif JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_TYPED_ARRAY_UL) +#else /* !(JERRY_BUILTIN_TYPEDARRAY) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_ALLSETTLED) +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (11, LIT_MAGIC_STRING_SOURCE_NAME_ANON) +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_FLOAT32_ARRAY_UL) +#elif JERRY_BUILTIN_TYPEDARRAY && JERRY_NUMBER_TYPE_FLOAT64 +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_FLOAT64_ARRAY_UL) +#elif JERRY_BUILTIN_DATE +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_INVALID_DATE_UL) +#else /* !(JERRY_BUILTIN_DATE) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (12, LIT_MAGIC_STRING_MAP_ITERATOR_UL) +#endif /* JERRY_BUILTIN_DATE */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (13, LIT_MAGIC_STRING_ASYNC_FUNCTION_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (14, LIT_MAGIC_STRING_AGGREGATE_ERROR_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (15, LIT_MAGIC_STRING_STRING_ITERATOR_UL) +#if JERRY_BUILTIN_NUMBER +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (16, LIT_MAGIC_STRING_MAX_SAFE_INTEGER_U) +#elif JERRY_BUILTIN_ANNEXB +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (16, LIT_MAGIC_STRING_DEFINE_GETTER) +#else /* !(JERRY_BUILTIN_ANNEXB) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (16, LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL) +#endif /* JERRY_BUILTIN_ANNEXB */ +#if JERRY_BUILTIN_TYPEDARRAY +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U) +#else /* !(JERRY_BUILTIN_TYPEDARRAY) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL) +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (18, LIT_MAGIC_STRING_DECODE_URI_COMPONENT) +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (19, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (19, LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL) +#endif /* JERRY_FUNCTION_TO_STRING */ +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (20, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (20, LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL) +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (21, LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (22, LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (23, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (24, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL) +#endif /* JERRY_FUNCTION_TO_STRING */ +#if JERRY_FUNCTION_TO_STRING +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (26, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR) +#else /* !(JERRY_FUNCTION_TO_STRING) */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (26, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +#endif /* JERRY_FUNCTION_TO_STRING */ +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (27, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (28, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (29, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE) +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (30, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA) +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (31, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA) +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ +#if JERRY_SNAPSHOT_EXEC || !(JERRY_FUNCTION_TO_STRING) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (32, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA) +#endif /* JERRY_SNAPSHOT_EXEC \ +|| !(JERRY_FUNCTION_TO_STRING) */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.cpp b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.cpp new file mode 100644 index 00000000..948b4ff1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.cpp @@ -0,0 +1,934 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lit-strings.h" + +#include "jrt-libc-includes.h" + +#define LIT_UTF8_SURROGATE_MARKER 0xed /**< utf8 surrogate marker */ +#define LIT_UTF8_HIGH_SURROGATE_MIN 0xa0 /**< utf8 high surrogate minimum */ +#define LIT_UTF8_HIGH_SURROGATE_MAX 0xaf /**< utf8 high surrogate maximum */ +#define LIT_UTF8_LOW_SURROGATE_MIN 0xb0 /**< utf8 low surrogate minimum */ +#define LIT_UTF8_LOW_SURROGATE_MAX 0xbf /**< utf8 low surrogate maximum */ +#define LIT_UTF8_1_BYTE_MAX 0xf4 /**< utf8 one byte max */ +#define LIT_UTF8_2_BYTE_MAX 0x8f /**< utf8 two byte max */ +#define LIT_UTF8_VALID_TWO_BYTE_START 0xc2 /**< utf8 two byte start */ + +/** + * Validate utf-8 string + * + * NOTE: + * Isolated surrogates are allowed. + * + * @return true if utf-8 string is well-formed + * false otherwise + */ +bool +lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */ + lit_utf8_size_t buf_size, /**< string size */ + bool is_strict) /**< true if surrogate pairs are not allowed */ +{ + const unsigned char *end = buf_size + utf8_buf_p; + + const unsigned char *idx = (const unsigned char *) utf8_buf_p; + + while (idx < end) + { + const uint8_t first_byte = *idx++; + + if (first_byte < LIT_UTF8_EXTRA_BYTE_MARKER) + { + continue; + } + + if (first_byte < LIT_UTF8_VALID_TWO_BYTE_START || idx >= end) + { + return false; + } + + const uint8_t second_byte = *idx++; + + if ((second_byte & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + + if (first_byte < LIT_UTF8_3_BYTE_MARKER) + { + continue; + } + + if (idx >= end || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + + if (first_byte < LIT_UTF8_4_BYTE_MARKER) + { + if (first_byte == LIT_UTF8_3_BYTE_MARKER && (second_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + + if (is_strict && first_byte == LIT_UTF8_SURROGATE_MARKER && second_byte >= LIT_UTF8_HIGH_SURROGATE_MIN + && second_byte <= LIT_UTF8_HIGH_SURROGATE_MAX && idx + 3 <= end && idx[0] == LIT_UTF8_SURROGATE_MARKER + && idx[1] >= LIT_UTF8_LOW_SURROGATE_MIN && idx[1] <= LIT_UTF8_LOW_SURROGATE_MAX) + { + return false; + } + continue; + } + + if (idx >= end || first_byte > LIT_UTF8_1_BYTE_MAX + || (first_byte == LIT_UTF8_4_BYTE_MARKER && second_byte <= LIT_UTF8_EXTRA_BYTE_MARKER) + || (first_byte == LIT_UTF8_1_BYTE_MAX && second_byte > LIT_UTF8_2_BYTE_MAX) + || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + return false; + } + } + + return true; +} /* lit_is_valid_utf8_string */ + +/** + * Validate cesu-8 string + * + * @return true if cesu-8 string is well-formed + * false otherwise + */ +bool +lit_is_valid_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< cesu-8 string */ + lit_utf8_size_t buf_size) /**< string size */ +{ + lit_utf8_size_t idx = 0; + + while (idx < buf_size) + { + lit_utf8_byte_t c = cesu8_buf_p[idx++]; + if ((c & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + continue; + } + + lit_code_point_t code_point = 0; + lit_code_point_t min_code_point = 0; + lit_utf8_size_t extra_bytes_count; + if ((c & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + extra_bytes_count = 1; + min_code_point = LIT_UTF8_2_BYTE_CODE_POINT_MIN; + code_point = ((uint32_t) (c & LIT_UTF8_LAST_5_BITS_MASK)); + } + else if ((c & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + extra_bytes_count = 2; + min_code_point = LIT_UTF8_3_BYTE_CODE_POINT_MIN; + code_point = ((uint32_t) (c & LIT_UTF8_LAST_4_BITS_MASK)); + } + else + { + return false; + } + + if (idx + extra_bytes_count > buf_size) + { + /* cesu-8 string breaks in the middle */ + return false; + } + + for (lit_utf8_size_t offset = 0; offset < extra_bytes_count; ++offset) + { + c = cesu8_buf_p[idx + offset]; + if ((c & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) + { + /* invalid continuation byte */ + return false; + } + code_point <<= LIT_UTF8_BITS_IN_EXTRA_BYTES; + code_point |= (c & LIT_UTF8_LAST_6_BITS_MASK); + } + + if (code_point < min_code_point) + { + /* cesu-8 string doesn't encode valid unicode code point */ + return false; + } + + idx += extra_bytes_count; + } + + return true; +} /* lit_is_valid_cesu8_string */ + +/** + * Check if the code point is UTF-16 low surrogate + * + * @return true / false + */ +bool +lit_is_code_point_utf16_low_surrogate (lit_code_point_t code_point) /**< code point */ +{ + return LIT_UTF16_LOW_SURROGATE_MIN <= code_point && code_point <= LIT_UTF16_LOW_SURROGATE_MAX; +} /* lit_is_code_point_utf16_low_surrogate */ + +/** + * Check if the code point is UTF-16 high surrogate + * + * @return true / false + */ +bool +lit_is_code_point_utf16_high_surrogate (lit_code_point_t code_point) /**< code point */ +{ + return LIT_UTF16_HIGH_SURROGATE_MIN <= code_point && code_point <= LIT_UTF16_HIGH_SURROGATE_MAX; +} /* lit_is_code_point_utf16_high_surrogate */ + +/** + * Represents code point (>0xFFFF) as surrogate pair and returns its lower part + * + * @return lower code_unit of the surrogate pair + */ +static ecma_char_t +convert_code_point_to_low_surrogate (lit_code_point_t code_point) /**< code point, should be > 0xFFFF */ +{ + JERRY_ASSERT (code_point > LIT_UTF16_CODE_UNIT_MAX); + + ecma_char_t code_unit_bits; + code_unit_bits = (ecma_char_t) (code_point & LIT_UTF16_LAST_10_BITS_MASK); + + return (ecma_char_t) (LIT_UTF16_LOW_SURROGATE_MARKER | code_unit_bits); +} /* convert_code_point_to_low_surrogate */ + +/** + * Represents code point (>0xFFFF) as surrogate pair and returns its higher part + * + * @return higher code_unit of the surrogate pair + */ +static ecma_char_t +convert_code_point_to_high_surrogate (lit_code_point_t code_point) /**< code point, should be > 0xFFFF */ +{ + JERRY_ASSERT (code_point > LIT_UTF16_CODE_UNIT_MAX); + JERRY_ASSERT (code_point <= LIT_UNICODE_CODE_POINT_MAX); + + ecma_char_t code_unit_bits; + code_unit_bits = (ecma_char_t) ((code_point - LIT_UTF16_FIRST_SURROGATE_CODE_POINT) >> LIT_UTF16_BITS_IN_SURROGATE); + + return (LIT_UTF16_HIGH_SURROGATE_MARKER | code_unit_bits); +} /* convert_code_point_to_high_surrogate */ + +/** + * UTF16 Encoding method for a code point + * + * See also: + * ECMA-262 v6, 10.1.1 + * + * @return uint8_t, the number of returning code points + */ +uint8_t +lit_utf16_encode_code_point (lit_code_point_t cp, /**< the code point we encode */ + ecma_char_t *cu_p) /**< result of the encoding */ +{ + if (cp <= LIT_UTF16_CODE_UNIT_MAX) + { + cu_p[0] = (ecma_char_t) cp; + return 1; + } + + cu_p[0] = convert_code_point_to_high_surrogate (cp); + cu_p[1] = convert_code_point_to_low_surrogate (cp); + return 2; +} /* lit_utf16_encode_code_point */ + +/** + * Calculate size of a zero-terminated utf-8 string + * + * NOTE: + * - string cannot be NULL + * - string should not contain zero characters in the middle + * + * @return size of a string + */ +lit_utf8_size_t +lit_zt_utf8_string_size (const lit_utf8_byte_t *utf8_str_p) /**< zero-terminated utf-8 string */ +{ + JERRY_ASSERT (utf8_str_p != NULL); + return (lit_utf8_size_t) strlen ((const char *) utf8_str_p); +} /* lit_zt_utf8_string_size */ + +/** + * Calculate length of a cesu-8 encoded string + * + * @return UTF-16 code units count + */ +lit_utf8_size_t +lit_utf8_string_length (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */ + lit_utf8_size_t utf8_buf_size) /**< string size */ +{ + lit_utf8_size_t length = 0; + lit_utf8_size_t size = 0; + + while (size < utf8_buf_size) + { + size += lit_get_unicode_char_size_by_utf8_first_byte (*(utf8_buf_p + size)); + length++; + } + + JERRY_ASSERT (size == utf8_buf_size); + + return length; +} /* lit_utf8_string_length */ + +/** + * Calculate the required size of an utf-8 encoded string from cesu-8 encoded string + * + * @return size of an utf-8 encoded string + */ +lit_utf8_size_t +lit_get_utf8_size_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< cesu-8 string */ + lit_utf8_size_t cesu8_buf_size) /**< string size */ +{ + lit_utf8_size_t offset = 0; + lit_utf8_size_t utf8_buf_size = cesu8_buf_size; + ecma_char_t prev_ch = 0; + + while (offset < cesu8_buf_size) + { + ecma_char_t ch; + offset += lit_read_code_unit_from_cesu8 (cesu8_buf_p + offset, &ch); + + if (lit_is_code_point_utf16_low_surrogate (ch) && lit_is_code_point_utf16_high_surrogate (prev_ch)) + { + utf8_buf_size -= 2; + } + + prev_ch = ch; + } + + JERRY_ASSERT (offset == cesu8_buf_size); + + return utf8_buf_size; +} /* lit_get_utf8_size_of_cesu8_string */ + +/** + * Calculate length of an utf-8 encoded string from cesu-8 encoded string + * + * @return length of an utf-8 encoded string + */ +lit_utf8_size_t +lit_get_utf8_length_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< cesu-8 string */ + lit_utf8_size_t cesu8_buf_size) /**< string size */ +{ + lit_utf8_size_t offset = 0; + lit_utf8_size_t utf8_length = 0; + ecma_char_t prev_ch = 0; + + while (offset < cesu8_buf_size) + { + ecma_char_t ch; + offset += lit_read_code_unit_from_cesu8 (cesu8_buf_p + offset, &ch); + + if (!lit_is_code_point_utf16_low_surrogate (ch) || !lit_is_code_point_utf16_high_surrogate (prev_ch)) + { + utf8_length++; + } + + prev_ch = ch; + } + + JERRY_ASSERT (offset == cesu8_buf_size); + + return utf8_length; +} /* lit_get_utf8_length_of_cesu8_string */ + +/** + * Decodes a unicode code point from non-empty utf-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_code_point_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + lit_utf8_size_t buf_size, /**< size of the buffer in bytes */ + lit_code_point_t *code_point) /**< [out] code point */ +{ + JERRY_ASSERT (buf_p && buf_size); + + lit_utf8_byte_t c = buf_p[0]; + if ((c & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + *code_point = (lit_code_point_t) (c & LIT_UTF8_LAST_7_BITS_MASK); + return 1; + } + + lit_code_point_t ret = LIT_UNICODE_CODE_POINT_NULL; + lit_utf8_size_t bytes_count = 0; + if ((c & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + bytes_count = 2; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_5_BITS_MASK)); + } + else if ((c & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) + { + bytes_count = 3; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_4_BITS_MASK)); + } + else + { + JERRY_ASSERT ((c & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER); + bytes_count = 4; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_3_BITS_MASK)); + } + + JERRY_ASSERT (buf_size >= bytes_count); + + for (uint32_t i = 1; i < bytes_count; ++i) + { + ret <<= LIT_UTF8_BITS_IN_EXTRA_BYTES; + ret |= (buf_p[i] & LIT_UTF8_LAST_6_BITS_MASK); + } + + *code_point = ret; + return bytes_count; +} /* lit_read_code_point_from_utf8 */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_code_unit_from_cesu8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + ecma_char_t *code_unit) /**< [out] code unit */ +{ + JERRY_ASSERT (buf_p); + + lit_utf8_byte_t c = buf_p[0]; + if ((c & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + *code_unit = (ecma_char_t) (c & LIT_UTF8_LAST_7_BITS_MASK); + return 1; + } + + lit_code_point_t ret = LIT_UNICODE_CODE_POINT_NULL; + lit_utf8_size_t bytes_count; + + if ((c & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + bytes_count = 2; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_5_BITS_MASK)); + } + else + { + JERRY_ASSERT ((c & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER); + bytes_count = 3; + ret = ((lit_code_point_t) (c & LIT_UTF8_LAST_4_BITS_MASK)); + } + + for (uint32_t i = 1; i < bytes_count; ++i) + { + ret <<= LIT_UTF8_BITS_IN_EXTRA_BYTES; + ret |= (buf_p[i] & LIT_UTF8_LAST_6_BITS_MASK); + } + + JERRY_ASSERT (ret <= LIT_UTF16_CODE_UNIT_MAX); + *code_unit = (ecma_char_t) ret; + return bytes_count; +} /* lit_read_code_unit_from_cesu8 */ + +/** + * Decodes a unicode code point from non-empty cesu-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_code_point_from_cesu8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + const lit_utf8_byte_t *buf_end_p, /**< buffer end */ + lit_code_point_t *code_point) /**< [out] code point */ +{ + ecma_char_t code_unit; + lit_utf8_size_t size = lit_read_code_unit_from_cesu8 (buf_p, &code_unit); + + JERRY_ASSERT (buf_p + size <= buf_end_p); + + if (lit_is_code_point_utf16_high_surrogate (code_unit)) + { + buf_p += size; + + if (buf_p < buf_end_p) + { + ecma_char_t next_code_unit; + lit_utf8_size_t next_size = lit_read_code_unit_from_cesu8 (buf_p, &next_code_unit); + + if (lit_is_code_point_utf16_low_surrogate (next_code_unit)) + { + JERRY_ASSERT (buf_p + next_size <= buf_end_p); + + *code_point = lit_convert_surrogate_pair_to_code_point (code_unit, next_code_unit); + return size + next_size; + } + } + } + + *code_point = code_unit; + return size; +} /* lit_read_code_point_from_cesu8 */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return number of bytes occupied by code point in the string + */ +lit_utf8_size_t +lit_read_prev_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */ + ecma_char_t *code_point) /**< [out] code point */ +{ + JERRY_ASSERT (buf_p); + + lit_utf8_decr (&buf_p); + return lit_read_code_unit_from_cesu8 (buf_p, code_point); +} /* lit_read_prev_code_unit_from_utf8 */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return next code unit + */ +ecma_char_t +lit_cesu8_read_next (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + ecma_char_t ch; + + *buf_p += lit_read_code_unit_from_cesu8 (*buf_p, &ch); + + return ch; +} /* lit_cesu8_read_next */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return previous code unit + */ +ecma_char_t +lit_cesu8_read_prev (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + ecma_char_t ch; + + lit_utf8_decr (buf_p); + lit_read_code_unit_from_cesu8 (*buf_p, &ch); + + return ch; +} /* lit_cesu8_read_prev */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return next code unit + */ +ecma_char_t JERRY_ATTR_NOINLINE +lit_cesu8_peek_next (const lit_utf8_byte_t *buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (buf_p != NULL); + ecma_char_t ch; + + lit_read_code_unit_from_cesu8 (buf_p, &ch); + + return ch; +} /* lit_cesu8_peek_next */ + +/** + * Decodes a unicode code unit from non-empty cesu-8-encoded buffer + * + * @return previous code unit + */ +ecma_char_t JERRY_ATTR_NOINLINE +lit_cesu8_peek_prev (const lit_utf8_byte_t *buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (buf_p != NULL); + ecma_char_t ch; + + lit_read_prev_code_unit_from_utf8 (buf_p, &ch); + + return ch; +} /* lit_cesu8_peek_prev */ + +/** + * Increase cesu-8 encoded string pointer by one code unit. + */ +void +lit_utf8_incr (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + + *buf_p += lit_get_unicode_char_size_by_utf8_first_byte (**buf_p); +} /* lit_utf8_incr */ + +/** + * Decrease cesu-8 encoded string pointer by one code unit. + */ +void +lit_utf8_decr (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with characters */ +{ + JERRY_ASSERT (*buf_p); + const lit_utf8_byte_t *current_p = *buf_p; + + do + { + current_p--; + } while ((*current_p & LIT_UTF8_EXTRA_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER); + + *buf_p = current_p; +} /* lit_utf8_decr */ + +/** + * Calc hash using the specified hash_basis. + * + * NOTE: + * This is implementation of FNV-1a hash function, which is released into public domain. + * Constants used, are carefully picked primes by the authors. + * More info: http://www.isthe.com/chongo/tech/comp/fnv/ + * + * @return ecma-string's hash + */ +lit_string_hash_t +lit_utf8_string_hash_combine (lit_string_hash_t hash_basis, /**< hash to be combined with */ + const lit_utf8_byte_t *utf8_buf_p, /**< characters buffer */ + lit_utf8_size_t utf8_buf_size) /**< number of characters in the buffer */ +{ + JERRY_ASSERT (utf8_buf_p != NULL || utf8_buf_size == 0); + + uint32_t hash = hash_basis; + + for (uint32_t i = 0; i < utf8_buf_size; i++) + { + /* 16777619 is 32 bit FNV_prime = 2^24 + 2^8 + 0x93 = 16777619 */ + hash = (hash ^ utf8_buf_p[i]) * 16777619; + } + + return (lit_string_hash_t) hash; +} /* lit_utf8_string_hash_combine */ + +/** + * Calculate hash from the buffer. + * + * @return ecma-string's hash + */ +lit_string_hash_t +lit_utf8_string_calc_hash (const lit_utf8_byte_t *utf8_buf_p, /**< characters buffer */ + lit_utf8_size_t utf8_buf_size) /**< number of characters in the buffer */ +{ + JERRY_ASSERT (utf8_buf_p != NULL || utf8_buf_size == 0); + + /* 32 bit offset_basis for FNV = 2166136261 */ + return lit_utf8_string_hash_combine ((lit_string_hash_t) 2166136261, utf8_buf_p, utf8_buf_size); +} /* lit_utf8_string_calc_hash */ + +/** + * Return code unit at the specified position in string + * + * NOTE: + * code_unit_offset should be less then string's length + * + * @return code unit value + */ +ecma_char_t +lit_utf8_string_code_unit_at (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */ + lit_utf8_size_t utf8_buf_size, /**< string size in bytes */ + lit_utf8_size_t code_unit_offset) /**< ofset of a code_unit */ +{ + lit_utf8_byte_t *current_p = (lit_utf8_byte_t *) utf8_buf_p; + ecma_char_t code_unit; + + do + { + JERRY_ASSERT (current_p < utf8_buf_p + utf8_buf_size); + current_p += lit_read_code_unit_from_cesu8 (current_p, &code_unit); + } while (code_unit_offset--); + + return code_unit; +} /* lit_utf8_string_code_unit_at */ + +/** + * Get CESU-8 encoded size of character + * + * @return number of bytes occupied in CESU-8 + */ +lit_utf8_size_t +lit_get_unicode_char_size_by_utf8_first_byte (const lit_utf8_byte_t first_byte) /**< buffer with characters */ +{ + if ((first_byte & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER) + { + return 1; + } + else if ((first_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) + { + return 2; + } + else + { + JERRY_ASSERT ((first_byte & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER); + return 3; + } +} /* lit_get_unicode_char_size_by_utf8_first_byte */ + +/** + * Convert code unit to cesu-8 representation + * + * @return byte count required to represent the code unit + */ +lit_utf8_size_t +lit_code_unit_to_utf8 (ecma_char_t code_unit, /**< code unit */ + lit_utf8_byte_t *buf_p) /**< buffer where to store the result and its size + * should be at least LIT_UTF8_MAX_BYTES_IN_CODE_UNIT */ +{ + if (code_unit <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + buf_p[0] = (lit_utf8_byte_t) code_unit; + return 1; + } + else if (code_unit <= LIT_UTF8_2_BYTE_CODE_POINT_MAX) + { + uint32_t code_unit_bits = code_unit; + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_unit_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_5_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_unit_bits); + + buf_p[0] = LIT_UTF8_2_BYTE_MARKER | first_byte_bits; + buf_p[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + return 2; + } + else + { + uint32_t code_unit_bits = code_unit; + lit_utf8_byte_t third_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_unit_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_unit_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_unit_bits & LIT_UTF8_LAST_4_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_unit_bits); + + buf_p[0] = LIT_UTF8_3_BYTE_MARKER | first_byte_bits; + buf_p[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + buf_p[2] = LIT_UTF8_EXTRA_BYTE_MARKER | third_byte_bits; + return 3; + } +} /* lit_code_unit_to_utf8 */ + +/** + * Convert code point to cesu-8 representation + * + * @return byte count required to represent the code point + */ +lit_utf8_size_t +lit_code_point_to_cesu8 (lit_code_point_t code_point, /**< code point */ + lit_utf8_byte_t *buf) /**< buffer where to store the result, + * its size should be at least 6 bytes */ +{ + if (code_point <= LIT_UTF16_CODE_UNIT_MAX) + { + return lit_code_unit_to_utf8 ((ecma_char_t) code_point, buf); + } + else + { + lit_utf8_size_t offset = lit_code_unit_to_utf8 (convert_code_point_to_high_surrogate (code_point), buf); + offset += lit_code_unit_to_utf8 (convert_code_point_to_low_surrogate (code_point), buf + offset); + return offset; + } +} /* lit_code_point_to_cesu8 */ + +/** + * Convert code point to utf-8 representation + * + * @return byte count required to represent the code point + */ +lit_utf8_size_t +lit_code_point_to_utf8 (lit_code_point_t code_point, /**< code point */ + lit_utf8_byte_t *buf) /**< buffer where to store the result, + * its size should be at least 4 bytes */ +{ + if (code_point <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + buf[0] = (lit_utf8_byte_t) code_point; + return 1; + } + else if (code_point <= LIT_UTF8_2_BYTE_CODE_POINT_MAX) + { + uint32_t code_point_bits = code_point; + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_5_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_point_bits); + + buf[0] = LIT_UTF8_2_BYTE_MARKER | first_byte_bits; + buf[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + return 2; + } + else if (code_point <= LIT_UTF8_3_BYTE_CODE_POINT_MAX) + { + uint32_t code_point_bits = code_point; + lit_utf8_byte_t third_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_4_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_point_bits); + + buf[0] = LIT_UTF8_3_BYTE_MARKER | first_byte_bits; + buf[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + buf[2] = LIT_UTF8_EXTRA_BYTE_MARKER | third_byte_bits; + return 3; + } + else + { + JERRY_ASSERT (code_point <= LIT_UTF8_4_BYTE_CODE_POINT_MAX); + + uint32_t code_point_bits = code_point; + lit_utf8_byte_t fourth_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t third_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t second_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_6_BITS_MASK); + code_point_bits >>= LIT_UTF8_BITS_IN_EXTRA_BYTES; + + lit_utf8_byte_t first_byte_bits = (lit_utf8_byte_t) (code_point_bits & LIT_UTF8_LAST_3_BITS_MASK); + JERRY_ASSERT (first_byte_bits == code_point_bits); + + buf[0] = LIT_UTF8_4_BYTE_MARKER | first_byte_bits; + buf[1] = LIT_UTF8_EXTRA_BYTE_MARKER | second_byte_bits; + buf[2] = LIT_UTF8_EXTRA_BYTE_MARKER | third_byte_bits; + buf[3] = LIT_UTF8_EXTRA_BYTE_MARKER | fourth_byte_bits; + return 4; + } +} /* lit_code_point_to_utf8 */ + +/** + * Convert cesu-8 string to an utf-8 string and put it into the buffer. + * String will be truncated to fit the buffer. + * + * @return number of bytes copied to the buffer. + */ +lit_utf8_size_t +lit_convert_cesu8_string_to_utf8_string (const lit_utf8_byte_t *cesu8_string_p, /**< cesu-8 string */ + lit_utf8_size_t cesu8_size, /**< size of cesu-8 string */ + lit_utf8_byte_t *utf8_string_p, /**< destination utf-8 buffer pointer + * (can be NULL if buffer_size == 0) */ + lit_utf8_size_t utf8_size) /**< size of utf-8 buffer */ +{ + const lit_utf8_byte_t *cesu8_cursor_p = cesu8_string_p; + const lit_utf8_byte_t *cesu8_end_p = cesu8_string_p + cesu8_size; + + lit_utf8_byte_t *utf8_cursor_p = utf8_string_p; + lit_utf8_byte_t *utf8_end_p = utf8_string_p + utf8_size; + + while (cesu8_cursor_p < cesu8_end_p) + { + lit_code_point_t cp; + lit_utf8_size_t read_size = lit_read_code_point_from_cesu8 (cesu8_cursor_p, cesu8_end_p, &cp); + lit_utf8_size_t encoded_size = (cp >= LIT_UTF16_FIRST_SURROGATE_CODE_POINT) ? 4 : read_size; + + if (utf8_cursor_p + encoded_size > utf8_end_p) + { + break; + } + + if (cp >= LIT_UTF16_FIRST_SURROGATE_CODE_POINT) + { + lit_code_point_to_utf8 (cp, utf8_cursor_p); + } + else + { + memcpy (utf8_cursor_p, cesu8_cursor_p, encoded_size); + } + + utf8_cursor_p += encoded_size; + cesu8_cursor_p += read_size; + } + + JERRY_ASSERT (cesu8_cursor_p <= cesu8_end_p); + JERRY_ASSERT (utf8_cursor_p <= utf8_end_p); + + return (lit_utf8_byte_t) (utf8_cursor_p - utf8_string_p); +} /* lit_convert_cesu8_string_to_utf8_string */ + +/** + * Convert surrogate pair to code point + * + * @return code point + */ +lit_code_point_t +lit_convert_surrogate_pair_to_code_point (ecma_char_t high_surrogate, /**< high surrogate code point */ + ecma_char_t low_surrogate) /**< low surrogate code point */ +{ + JERRY_ASSERT (lit_is_code_point_utf16_high_surrogate (high_surrogate)); + JERRY_ASSERT (lit_is_code_point_utf16_low_surrogate (low_surrogate)); + + lit_code_point_t code_point; + code_point = (uint16_t) (high_surrogate - LIT_UTF16_HIGH_SURROGATE_MIN); + code_point <<= LIT_UTF16_BITS_IN_SURROGATE; + + code_point += LIT_UTF16_FIRST_SURROGATE_CODE_POINT; + + code_point |= (uint16_t) (low_surrogate - LIT_UTF16_LOW_SURROGATE_MIN); + return code_point; +} /* lit_convert_surrogate_pair_to_code_point */ + +/** + * Relational compare of cesu-8 strings + * + * First string is less than second string if: + * - strings are not equal; + * - first string is prefix of second or is lexicographically less than second. + * + * @return true - if first string is less than second string, + * false - otherwise + */ +bool +lit_compare_utf8_strings_relational (const lit_utf8_byte_t *string1_p, /**< utf-8 string */ + lit_utf8_size_t string1_size, /**< string size */ + const lit_utf8_byte_t *string2_p, /**< utf-8 string */ + lit_utf8_size_t string2_size) /**< string size */ +{ + lit_utf8_byte_t *string1_pos = (lit_utf8_byte_t *) string1_p; + lit_utf8_byte_t *string2_pos = (lit_utf8_byte_t *) string2_p; + const lit_utf8_byte_t *string1_end_p = string1_p + string1_size; + const lit_utf8_byte_t *string2_end_p = string2_p + string2_size; + + while (string1_pos < string1_end_p && string2_pos < string2_end_p) + { + ecma_char_t ch1, ch2; + string1_pos += lit_read_code_unit_from_cesu8 (string1_pos, &ch1); + string2_pos += lit_read_code_unit_from_cesu8 (string2_pos, &ch2); + + if (ch1 < ch2) + { + return true; + } + else if (ch1 > ch2) + { + return false; + } + } + + return (string1_pos >= string1_end_p && string2_pos < string2_end_p); +} /* lit_compare_utf8_strings_relational */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.h new file mode 100644 index 00000000..d00480e6 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-strings.h @@ -0,0 +1,150 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_STRINGS_H +#define LIT_STRINGS_H + +#include "jrt.h" +#include "lit-globals.h" + +/** + * Null character (used in few cases as utf-8 string end marker) + */ +#define LIT_BYTE_NULL (0) + +/** + * For the formal definition of Unicode transformation formats (UTF) see Section 3.9, Unicode Encoding Forms in The + * Unicode Standard (http://www.unicode.org/versions/Unicode3.0.0/ch03.pdf#G7404). + */ +#define LIT_UNICODE_CODE_POINT_NULL (0x0) +#define LIT_UNICODE_CODE_POINT_MAX (0x10FFFF) + +#define LIT_UTF16_CODE_UNIT_MAX (0xFFFF) +#define LIT_UTF16_FIRST_SURROGATE_CODE_POINT (0x10000) +#define LIT_UTF16_LOW_SURROGATE_MARKER (0xDC00) +#define LIT_UTF16_HIGH_SURROGATE_MARKER (0xD800) +#define LIT_UTF16_HIGH_SURROGATE_MIN (0xD800) +#define LIT_UTF16_HIGH_SURROGATE_MAX (0xDBFF) +#define LIT_UTF16_LOW_SURROGATE_MIN (0xDC00) +#define LIT_UTF16_LOW_SURROGATE_MAX (0xDFFF) +#define LIT_UTF16_BITS_IN_SURROGATE (10) +#define LIT_UTF16_LAST_10_BITS_MASK (0x3FF) + +#define LIT_UTF8_1_BYTE_MARKER (0x00) +#define LIT_UTF8_2_BYTE_MARKER (0xC0) +#define LIT_UTF8_3_BYTE_MARKER (0xE0) +#define LIT_UTF8_4_BYTE_MARKER (0xF0) +#define LIT_UTF8_EXTRA_BYTE_MARKER (0x80) + +#define LIT_UTF8_1_BYTE_MASK (0x80) +#define LIT_UTF8_2_BYTE_MASK (0xE0) +#define LIT_UTF8_3_BYTE_MASK (0xF0) +#define LIT_UTF8_4_BYTE_MASK (0xF8) +#define LIT_UTF8_EXTRA_BYTE_MASK (0xC0) + +#define LIT_UTF8_LAST_7_BITS_MASK (0x7F) +#define LIT_UTF8_LAST_6_BITS_MASK (0x3F) +#define LIT_UTF8_LAST_5_BITS_MASK (0x1F) +#define LIT_UTF8_LAST_4_BITS_MASK (0x0F) +#define LIT_UTF8_LAST_3_BITS_MASK (0x07) +#define LIT_UTF8_LAST_2_BITS_MASK (0x03) +#define LIT_UTF8_LAST_1_BIT_MASK (0x01) + +#define LIT_UTF8_BITS_IN_EXTRA_BYTES (6) + +#define LIT_UTF8_1_BYTE_CODE_POINT_MAX (0x7F) +#define LIT_UTF8_2_BYTE_CODE_POINT_MIN (0x80) +#define LIT_UTF8_2_BYTE_CODE_POINT_MAX (0x7FF) +#define LIT_UTF8_3_BYTE_CODE_POINT_MIN (0x800) +#define LIT_UTF8_3_BYTE_CODE_POINT_MAX (LIT_UTF16_CODE_UNIT_MAX) +#define LIT_UTF8_4_BYTE_CODE_POINT_MIN (0x10000) +#define LIT_UTF8_4_BYTE_CODE_POINT_MAX (LIT_UNICODE_CODE_POINT_MAX) + +/** + * Differnce between byte count needed to represent code point greater than 0xFFFF + * in common UTF-8 (4 bytes required) and CESU-8 (6 bytes required) + */ +#define LIT_UTF8_CESU8_SURROGATE_SIZE_DIF (2 * LIT_UTF8_MAX_BYTES_IN_CODE_UNIT - LIT_UTF8_MAX_BYTES_IN_CODE_POINT) + +/** + * Byte values >= LIT_UTF8_FIRST_BYTE_MAX are not allowed in internal strings + */ +#define LIT_UTF8_FIRST_BYTE_MAX (0xF8) + +/* validation */ +bool lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t buf_size, bool strict); +bool lit_is_valid_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, lit_utf8_size_t buf_size); + +/* checks */ +bool lit_is_code_point_utf16_low_surrogate (lit_code_point_t code_point); +bool lit_is_code_point_utf16_high_surrogate (lit_code_point_t code_point); + +/* size */ +lit_utf8_size_t lit_zt_utf8_string_size (const lit_utf8_byte_t *utf8_str_p); +lit_utf8_size_t lit_get_utf8_size_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, lit_utf8_size_t cesu8_buf_size); + +/* length */ +lit_utf8_size_t lit_utf8_string_length (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t utf8_buf_size); +lit_utf8_size_t lit_get_utf8_length_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, + lit_utf8_size_t cesu8_buf_size); + +/* hash */ +lit_string_hash_t lit_utf8_string_calc_hash (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t utf8_buf_size); +lit_string_hash_t lit_utf8_string_hash_combine (lit_string_hash_t hash_basis, + const lit_utf8_byte_t *utf8_buf_p, + lit_utf8_size_t utf8_buf_size); + +/* code unit access */ +ecma_char_t lit_utf8_string_code_unit_at (const lit_utf8_byte_t *utf8_buf_p, + lit_utf8_size_t utf8_buf_size, + lit_utf8_size_t code_unit_offset); +lit_utf8_size_t lit_get_unicode_char_size_by_utf8_first_byte (const lit_utf8_byte_t first_byte); + +/* conversion */ +lit_utf8_size_t lit_code_unit_to_utf8 (ecma_char_t code_unit, lit_utf8_byte_t *buf_p); +lit_utf8_size_t lit_code_point_to_utf8 (lit_code_point_t code_point, lit_utf8_byte_t *buf); +lit_utf8_size_t lit_code_point_to_cesu8 (lit_code_point_t code_point, lit_utf8_byte_t *buf); +lit_utf8_size_t lit_convert_cesu8_string_to_utf8_string (const lit_utf8_byte_t *cesu8_string_p, + lit_utf8_size_t cesu8_size, + lit_utf8_byte_t *utf8_string_p, + lit_utf8_size_t utf8_size); +lit_code_point_t lit_convert_surrogate_pair_to_code_point (ecma_char_t high_surrogate, ecma_char_t low_surrogate); + +bool lit_compare_utf8_strings_relational (const lit_utf8_byte_t *string1_p, + lit_utf8_size_t string1_size, + const lit_utf8_byte_t *string2_p, + lit_utf8_size_t string2_size); + +uint8_t lit_utf16_encode_code_point (lit_code_point_t cp, ecma_char_t *cu_p); + +/* read code point from buffer */ +lit_utf8_size_t +lit_read_code_point_from_utf8 (const lit_utf8_byte_t *buf_p, lit_utf8_size_t buf_size, lit_code_point_t *code_point); + +lit_utf8_size_t lit_read_code_unit_from_cesu8 (const lit_utf8_byte_t *buf_p, ecma_char_t *code_unit); +lit_utf8_size_t lit_read_code_point_from_cesu8 (const lit_utf8_byte_t *buf_p, + const lit_utf8_byte_t *buf_end_p, + lit_code_point_t *code_point); + +lit_utf8_size_t lit_read_prev_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p, ecma_char_t *code_point); + +ecma_char_t lit_cesu8_read_next (const lit_utf8_byte_t **buf_p); +ecma_char_t lit_cesu8_read_prev (const lit_utf8_byte_t **buf_p); +ecma_char_t lit_cesu8_peek_next (const lit_utf8_byte_t *buf_p); +ecma_char_t lit_cesu8_peek_prev (const lit_utf8_byte_t *buf_p); +void lit_utf8_incr (const lit_utf8_byte_t **buf_p); +void lit_utf8_decr (const lit_utf8_byte_t **buf_p); + +#endif /* !LIT_STRINGS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions-sup.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions-sup.inc.h new file mode 100644 index 00000000..5a12a334 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions-sup.inc.h @@ -0,0 +1,27 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from UnicodeData.txt and SpecialCasing.txt files. Do not edit! */ + +/* Contains start points of character case ranges (these are bidirectional conversions). */ +static const uint32_t lit_unicode_character_case_ranges_sup[] JERRY_ATTR_CONST_DATA = { + 0x010400, 0x010428, 0x0104b0, 0x0104d8, 0x010c80, 0x010cc0, 0x0118a0, 0x0118c0, 0x016e40, 0x016e60, 0x01e900, 0x01e922 +}; + +/* Interval lengths of start points in `character_case_ranges` table. */ +static const uint16_t lit_unicode_character_case_range_lengths_sup[] JERRY_ATTR_CONST_DATA = { 0x000028, 0x000024, + 0x000033, 0x000020, + 0x000020, 0x000022 }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions.inc.h new file mode 100644 index 00000000..7c6279b2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-conversions.inc.h @@ -0,0 +1,119 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from UnicodeData.txt and SpecialCasing.txt files. Do not edit! */ + +/* Contains start points of character case ranges (these are bidirectional conversions). */ +static const uint16_t lit_unicode_character_case_ranges[] JERRY_ATTR_CONST_DATA = { + 0x00c0, 0x00e0, 0x00d8, 0x00f8, 0x0189, 0x0256, 0x01b1, 0x028a, 0x0388, 0x03ad, 0x038e, 0x03cd, 0x0391, + 0x03b1, 0x03a3, 0x03c3, 0x03fd, 0x037b, 0x0400, 0x0450, 0x0410, 0x0430, 0x0531, 0x0561, 0x10a0, 0x2d00, + 0x13a0, 0xab70, 0x13f0, 0x13f8, 0x1c90, 0x10d0, 0x1cbd, 0x10fd, 0x1f08, 0x1f00, 0x1f18, 0x1f10, 0x1f28, + 0x1f20, 0x1f38, 0x1f30, 0x1f48, 0x1f40, 0x1f68, 0x1f60, 0x1fb8, 0x1fb0, 0x1fba, 0x1f70, 0x1fc8, 0x1f72, + 0x1fd8, 0x1fd0, 0x1fda, 0x1f76, 0x1fe8, 0x1fe0, 0x1fea, 0x1f7a, 0x1ff8, 0x1f78, 0x1ffa, 0x1f7c, 0x2160, + 0x2170, 0x24b6, 0x24d0, 0x2c00, 0x2c30, 0x2c7e, 0x023f, 0xff21, 0xff41 +}; + +/* Interval lengths of start points in `character_case_ranges` table. */ +static const uint8_t lit_unicode_character_case_range_lengths[] JERRY_ATTR_CONST_DATA = { + 0x0017, 0x0007, 0x0002, 0x0002, 0x0003, 0x0002, 0x0011, 0x0009, 0x0003, 0x0010, 0x0020, 0x0026, 0x0026, + 0x0050, 0x0006, 0x002b, 0x0003, 0x0008, 0x0006, 0x0008, 0x0008, 0x0006, 0x0008, 0x0002, 0x0002, 0x0004, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x001a, 0x002f, 0x0002, 0x001a +}; + +/* Contains the start points of bidirectional conversion ranges. */ +static const uint16_t lit_unicode_character_pair_ranges[] JERRY_ATTR_CONST_DATA = { + 0x0100, 0x0132, 0x0139, 0x014a, 0x0179, 0x0182, 0x0187, 0x018b, 0x0191, 0x0198, 0x01a0, 0x01a7, + 0x01ac, 0x01af, 0x01b3, 0x01b8, 0x01bc, 0x01cd, 0x01de, 0x01f4, 0x01f8, 0x0222, 0x023b, 0x0241, + 0x0246, 0x0370, 0x0376, 0x03d8, 0x03f7, 0x03fa, 0x0460, 0x048a, 0x04c1, 0x04d0, 0x1e00, 0x1ea0, + 0x2183, 0x2c60, 0x2c67, 0x2c72, 0x2c75, 0x2c80, 0x2ceb, 0x2cf2, 0xa640, 0xa680, 0xa722, 0xa732, + 0xa779, 0xa77e, 0xa78b, 0xa790, 0xa796, 0xa7b4, 0xa7c2, 0xa7c7, 0xa7f5 +}; + +/* Interval lengths of start points in `character_pair_ranges` table. */ +static const uint8_t lit_unicode_character_pair_range_lengths[] JERRY_ATTR_CONST_DATA = { + 0x0030, 0x0006, 0x0010, 0x002e, 0x0006, 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0006, 0x0002, + 0x0002, 0x0002, 0x0004, 0x0002, 0x0002, 0x0010, 0x0012, 0x0002, 0x0028, 0x0012, 0x0002, 0x0002, + 0x000a, 0x0004, 0x0002, 0x0018, 0x0002, 0x0002, 0x0022, 0x0036, 0x000e, 0x0060, 0x0096, 0x0060, + 0x0002, 0x0002, 0x0006, 0x0002, 0x0002, 0x0064, 0x0004, 0x0002, 0x002e, 0x001c, 0x000e, 0x003e, + 0x0004, 0x000a, 0x0002, 0x0004, 0x0014, 0x000c, 0x0002, 0x0004, 0x0002 +}; + +/* Contains lower/upper case bidirectional conversion pairs. */ +static const uint16_t lit_unicode_character_pairs[] JERRY_ATTR_CONST_DATA = { + 0x0178, 0x00ff, 0x0181, 0x0253, 0x0186, 0x0254, 0x018e, 0x01dd, 0x018f, 0x0259, 0x0190, 0x025b, 0x0193, + 0x0260, 0x0194, 0x0263, 0x0196, 0x0269, 0x0197, 0x0268, 0x019c, 0x026f, 0x019d, 0x0272, 0x019f, 0x0275, + 0x01a6, 0x0280, 0x01a9, 0x0283, 0x01ae, 0x0288, 0x01b7, 0x0292, 0x01c4, 0x01c6, 0x01c7, 0x01c9, 0x01ca, + 0x01cc, 0x01f1, 0x01f3, 0x01f6, 0x0195, 0x01f7, 0x01bf, 0x0220, 0x019e, 0x023a, 0x2c65, 0x023d, 0x019a, + 0x023e, 0x2c66, 0x0243, 0x0180, 0x0244, 0x0289, 0x0245, 0x028c, 0x037f, 0x03f3, 0x0386, 0x03ac, 0x038c, + 0x03cc, 0x03cf, 0x03d7, 0x03f9, 0x03f2, 0x04c0, 0x04cf, 0x10c7, 0x2d27, 0x10cd, 0x2d2d, 0x1f59, 0x1f51, + 0x1f5b, 0x1f53, 0x1f5d, 0x1f55, 0x1f5f, 0x1f57, 0x1fec, 0x1fe5, 0x2132, 0x214e, 0x2c62, 0x026b, 0x2c63, + 0x1d7d, 0x2c64, 0x027d, 0x2c6d, 0x0251, 0x2c6e, 0x0271, 0x2c6f, 0x0250, 0x2c70, 0x0252, 0xa77d, 0x1d79, + 0xa78d, 0x0265, 0xa7aa, 0x0266, 0xa7ab, 0x025c, 0xa7ac, 0x0261, 0xa7ad, 0x026c, 0xa7ae, 0x026a, 0xa7b0, + 0x029e, 0xa7b1, 0x0287, 0xa7b2, 0x029d, 0xa7b3, 0xab53, 0xa7c4, 0xa794, 0xa7c5, 0x0282, 0xa7c6, 0x1d8e +}; + +/* Contains start points of one-to-two uppercase ranges where the second character + * is always the same. + */ +static const uint16_t lit_unicode_upper_case_special_ranges[] JERRY_ATTR_CONST_DATA = { + 0x1f80, 0x1f08, 0x0399, 0x1f88, 0x1f08, 0x0399, 0x1f90, 0x1f28, 0x0399, + 0x1f98, 0x1f28, 0x0399, 0x1fa0, 0x1f68, 0x0399, 0x1fa8, 0x1f68, 0x0399 +}; + +/* Interval lengths for start points in `upper_case_special_ranges` table. */ +static const uint8_t lit_unicode_upper_case_special_range_lengths[] JERRY_ATTR_CONST_DATA = { 0x0007, 0x0007, 0x0007, + 0x0007, 0x0007, 0x0007 }; + +/* Contains start points of lowercase ranges. */ +static const uint16_t lit_unicode_lower_case_ranges[] JERRY_ATTR_CONST_DATA = { 0x1f88, 0x1f80, 0x1f98, + 0x1f90, 0x1fa8, 0x1fa0 }; + +/* Interval lengths for start points in `lower_case_ranges` table. */ +static const uint8_t lit_unicode_lower_case_range_lengths[] JERRY_ATTR_CONST_DATA = { 0x0008, 0x0008, 0x0008 }; + +/* The remaining lowercase conversions. The lowercase variant can be one-to-three character long. */ +static const uint16_t lit_unicode_lower_case_conversions[] JERRY_ATTR_CONST_DATA = { + 0x01c5, 0x01c6, 0x01c8, 0x01c9, 0x01cb, 0x01cc, 0x01f2, 0x01f3, 0x03f4, 0x03b8, 0x1e9e, 0x00df, 0x1fbc, 0x1fb3, + 0x1fcc, 0x1fc3, 0x1ffc, 0x1ff3, 0x2126, 0x03c9, 0x212a, 0x006b, 0x212b, 0x00e5, 0x0130, 0x0069, 0x0307 +}; + +/* Number of one-to-one, one-to-two, and one-to-three lowercase conversions. */ +static const uint8_t lit_unicode_lower_case_conversion_counters[] JERRY_ATTR_CONST_DATA = { 0x000c, 0x0001, 0x0000 }; + +/* The remaining uppercase conversions. The uppercase variant can be one-to-three character long. */ +static const uint16_t lit_unicode_upper_case_conversions[] JERRY_ATTR_CONST_DATA = { + 0x00b5, 0x039c, 0x0131, 0x0049, 0x017f, 0x0053, 0x01c5, 0x01c4, 0x01c8, 0x01c7, 0x01cb, 0x01ca, 0x01f2, 0x01f1, + 0x0345, 0x0399, 0x03c2, 0x03a3, 0x03d0, 0x0392, 0x03d1, 0x0398, 0x03d5, 0x03a6, 0x03d6, 0x03a0, 0x03f0, 0x039a, + 0x03f1, 0x03a1, 0x03f5, 0x0395, 0x1c80, 0x0412, 0x1c81, 0x0414, 0x1c82, 0x041e, 0x1c83, 0x0421, 0x1c84, 0x0422, + 0x1c85, 0x0422, 0x1c86, 0x042a, 0x1c87, 0x0462, 0x1c88, 0xa64a, 0x1e9b, 0x1e60, 0x1fbe, 0x0399, 0x00df, 0x0053, + 0x0053, 0x0149, 0x02bc, 0x004e, 0x01f0, 0x004a, 0x030c, 0x0587, 0x0535, 0x0552, 0x1e96, 0x0048, 0x0331, 0x1e97, + 0x0054, 0x0308, 0x1e98, 0x0057, 0x030a, 0x1e99, 0x0059, 0x030a, 0x1e9a, 0x0041, 0x02be, 0x1f50, 0x03a5, 0x0313, + 0x1f87, 0x1f0f, 0x0399, 0x1f8f, 0x1f0f, 0x0399, 0x1f97, 0x1f2f, 0x0399, 0x1f9f, 0x1f2f, 0x0399, 0x1fa7, 0x1f6f, + 0x0399, 0x1faf, 0x1f6f, 0x0399, 0x1fb2, 0x1fba, 0x0399, 0x1fb3, 0x0391, 0x0399, 0x1fb4, 0x0386, 0x0399, 0x1fb6, + 0x0391, 0x0342, 0x1fbc, 0x0391, 0x0399, 0x1fc2, 0x1fca, 0x0399, 0x1fc3, 0x0397, 0x0399, 0x1fc4, 0x0389, 0x0399, + 0x1fc6, 0x0397, 0x0342, 0x1fcc, 0x0397, 0x0399, 0x1fd6, 0x0399, 0x0342, 0x1fe4, 0x03a1, 0x0313, 0x1fe6, 0x03a5, + 0x0342, 0x1ff2, 0x1ffa, 0x0399, 0x1ff3, 0x03a9, 0x0399, 0x1ff4, 0x038f, 0x0399, 0x1ff6, 0x03a9, 0x0342, 0x1ffc, + 0x03a9, 0x0399, 0xfb00, 0x0046, 0x0046, 0xfb01, 0x0046, 0x0049, 0xfb02, 0x0046, 0x004c, 0xfb05, 0x0053, 0x0054, + 0xfb06, 0x0053, 0x0054, 0xfb13, 0x0544, 0x0546, 0xfb14, 0x0544, 0x0535, 0xfb15, 0x0544, 0x053b, 0xfb16, 0x054e, + 0x0546, 0xfb17, 0x0544, 0x053d, 0x0390, 0x0399, 0x0308, 0x0301, 0x03b0, 0x03a5, 0x0308, 0x0301, 0x1f52, 0x03a5, + 0x0313, 0x0300, 0x1f54, 0x03a5, 0x0313, 0x0301, 0x1f56, 0x03a5, 0x0313, 0x0342, 0x1fb7, 0x0391, 0x0342, 0x0399, + 0x1fc7, 0x0397, 0x0342, 0x0399, 0x1fd2, 0x0399, 0x0308, 0x0300, 0x1fd3, 0x0399, 0x0308, 0x0301, 0x1fd7, 0x0399, + 0x0308, 0x0342, 0x1fe2, 0x03a5, 0x0308, 0x0300, 0x1fe3, 0x03a5, 0x0308, 0x0301, 0x1fe7, 0x03a5, 0x0308, 0x0342, + 0x1ff7, 0x03a9, 0x0342, 0x0399, 0xfb03, 0x0046, 0x0046, 0x0049, 0xfb04, 0x0046, 0x0046, 0x004c +}; + +/* Number of one-to-one, one-to-two, and one-to-three uppercase conversions. */ +static const uint8_t lit_unicode_upper_case_conversion_counters[] JERRY_ATTR_CONST_DATA = { 0x001b, 0x002c, 0x0010 }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-folding.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-folding.inc.h new file mode 100644 index 00000000..d9cd46f1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-folding.inc.h @@ -0,0 +1,54 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from the CaseFolding.txt file. Do not edit! */ + +/** + * Character interval starting points for folding_skip_to_lower. + */ +static const uint16_t lit_unicode_folding_skip_to_lower_interval_starts[] JERRY_ATTR_CONST_DATA = { 0x13a0, + 0x13f8, + 0xab70 }; + +/** + * Character interval lengths for folding_skip_to_lower. + */ +static const uint8_t lit_unicode_folding_skip_to_lower_interval_lengths[] JERRY_ATTR_CONST_DATA = { 0x0055, + 0x0005, + 0x004f }; + +/** + * Non-interval characters for folding_skip_to_lower. + */ +static const uint16_t lit_unicode_folding_skip_to_lower_chars[] JERRY_ATTR_CONST_DATA = { 0x0130 }; + +/** + * Character interval starting points for folding_to_upper. + */ +static const uint16_t lit_unicode_folding_to_upper_interval_starts[] JERRY_ATTR_CONST_DATA = { 0x03d0, 0x03d5, 0x03f0, + 0x13f8, 0x1c80, 0xab70 }; + +/** + * Character interval lengths for folding_to_upper. + */ +static const uint8_t lit_unicode_folding_to_upper_interval_lengths[] JERRY_ATTR_CONST_DATA = { 0x0001, 0x0001, 0x0001, + 0x0005, 0x0008, 0x004f }; + +/** + * Non-interval characters for folding_to_upper. + */ +static const uint16_t lit_unicode_folding_to_upper_chars[] JERRY_ATTR_CONST_DATA = { 0x00b5, 0x017f, 0x0345, 0x03c2, + 0x03f5, 0x1e9b, 0x1fbe }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges-sup.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges-sup.inc.h new file mode 100644 index 00000000..2e034faa --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges-sup.inc.h @@ -0,0 +1,116 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from DerivedCoreProperties.txt. Do not edit! */ + +/** + * Character interval starting points for ID_Start. + */ +static const uint32_t lit_unicode_id_start_interval_starts_sup[] JERRY_ATTR_CONST_DATA = { + 0x010000, 0x01000d, 0x010028, 0x01003c, 0x01003f, 0x010050, 0x010080, 0x010140, 0x010280, 0x0102a0, 0x010300, + 0x01032d, 0x010350, 0x010380, 0x0103a0, 0x0103c8, 0x0103d1, 0x010400, 0x0104b0, 0x0104d8, 0x010500, 0x010530, + 0x010600, 0x010740, 0x010760, 0x010800, 0x01080a, 0x010837, 0x01083f, 0x010860, 0x010880, 0x0108e0, 0x0108f4, + 0x010900, 0x010920, 0x010980, 0x0109be, 0x010a10, 0x010a15, 0x010a19, 0x010a60, 0x010a80, 0x010ac0, 0x010ac9, + 0x010b00, 0x010b40, 0x010b60, 0x010b80, 0x010c00, 0x010c80, 0x010cc0, 0x010d00, 0x010e80, 0x010eb0, 0x010f00, + 0x010f30, 0x010fb0, 0x010fe0, 0x011003, 0x011083, 0x0110d0, 0x011103, 0x011150, 0x011183, 0x0111c1, 0x011200, + 0x011213, 0x011280, 0x01128a, 0x01128f, 0x01129f, 0x0112b0, 0x011305, 0x01130f, 0x011313, 0x01132a, 0x011332, + 0x011335, 0x01135d, 0x011400, 0x011447, 0x01145f, 0x011480, 0x0114c4, 0x011580, 0x0115d8, 0x011600, 0x011680, + 0x011700, 0x011800, 0x0118a0, 0x0118ff, 0x01190c, 0x011915, 0x011918, 0x0119a0, 0x0119aa, 0x011a0b, 0x011a5c, + 0x011ac0, 0x011c00, 0x011c0a, 0x011c72, 0x011d00, 0x011d08, 0x011d0b, 0x011d60, 0x011d67, 0x011d6a, 0x011ee0, + 0x012000, 0x012400, 0x012480, 0x013000, 0x014400, 0x016800, 0x016a40, 0x016ad0, 0x016b00, 0x016b40, 0x016b63, + 0x016b7d, 0x016e40, 0x016f00, 0x016f93, 0x016fe0, 0x017000, 0x018800, 0x018d00, 0x01b000, 0x01b150, 0x01b164, + 0x01b170, 0x01bc00, 0x01bc70, 0x01bc80, 0x01bc90, 0x01d400, 0x01d456, 0x01d49e, 0x01d4a5, 0x01d4a9, 0x01d4ae, + 0x01d4bd, 0x01d4c5, 0x01d507, 0x01d50d, 0x01d516, 0x01d51e, 0x01d53b, 0x01d540, 0x01d54a, 0x01d552, 0x01d6a8, + 0x01d6c2, 0x01d6dc, 0x01d6fc, 0x01d716, 0x01d736, 0x01d750, 0x01d770, 0x01d78a, 0x01d7aa, 0x01d7c4, 0x01e100, + 0x01e137, 0x01e2c0, 0x01e800, 0x01e900, 0x01ee00, 0x01ee05, 0x01ee21, 0x01ee29, 0x01ee34, 0x01ee4d, 0x01ee51, + 0x01ee61, 0x01ee67, 0x01ee6c, 0x01ee74, 0x01ee79, 0x01ee80, 0x01ee8b, 0x01eea1, 0x01eea5, 0x01eeab, 0x020000, + 0x02a700, 0x02b740, 0x02b820, 0x02ceb0, 0x02f800, 0x030000 +}; + +/** + * Character interval lengths for ID_Start. + */ +static const uint16_t lit_unicode_id_start_interval_lengths_sup[] JERRY_ATTR_CONST_DATA = { + 0x00000b, 0x000019, 0x000012, 0x000001, 0x00000e, 0x00000d, 0x00007a, 0x000034, 0x00001c, 0x000030, 0x00001f, + 0x00001d, 0x000025, 0x00001d, 0x000023, 0x000007, 0x000004, 0x00009d, 0x000023, 0x000023, 0x000027, 0x000033, + 0x000136, 0x000015, 0x000007, 0x000005, 0x00002b, 0x000001, 0x000016, 0x000016, 0x00001e, 0x000012, 0x000001, + 0x000015, 0x000019, 0x000037, 0x000001, 0x000003, 0x000002, 0x00001c, 0x00001c, 0x00001c, 0x000007, 0x00001b, + 0x000035, 0x000015, 0x000012, 0x000011, 0x000048, 0x000032, 0x000032, 0x000023, 0x000029, 0x000001, 0x00001c, + 0x000015, 0x000014, 0x000016, 0x000034, 0x00002c, 0x000018, 0x000023, 0x000022, 0x00002f, 0x000003, 0x000011, + 0x000018, 0x000006, 0x000003, 0x00000e, 0x000009, 0x00002e, 0x000007, 0x000001, 0x000015, 0x000006, 0x000001, + 0x000004, 0x000004, 0x000034, 0x000003, 0x000002, 0x00002f, 0x000001, 0x00002e, 0x000003, 0x00002f, 0x00002a, + 0x00001a, 0x00002b, 0x00003f, 0x000007, 0x000007, 0x000001, 0x000017, 0x000007, 0x000026, 0x000027, 0x00002d, + 0x000038, 0x000008, 0x000024, 0x00001d, 0x000006, 0x000001, 0x000025, 0x000005, 0x000001, 0x00001f, 0x000012, + 0x000399, 0x00006e, 0x0000c3, 0x00042e, 0x000246, 0x000238, 0x00001e, 0x00001d, 0x00002f, 0x000003, 0x000014, + 0x000012, 0x00003f, 0x00004a, 0x00000c, 0x000001, 0x0017f7, 0x0004d5, 0x000008, 0x00011e, 0x000002, 0x000003, + 0x00018b, 0x00006a, 0x00000c, 0x000008, 0x000009, 0x000054, 0x000046, 0x000001, 0x000001, 0x000003, 0x00000b, + 0x000006, 0x000040, 0x000003, 0x000007, 0x000006, 0x00001b, 0x000003, 0x000004, 0x000006, 0x000153, 0x000018, + 0x000018, 0x00001e, 0x000018, 0x00001e, 0x000018, 0x00001e, 0x000018, 0x00001e, 0x000018, 0x000007, 0x00002c, + 0x000006, 0x00002b, 0x0000c4, 0x000043, 0x000003, 0x00001a, 0x000001, 0x000009, 0x000003, 0x000002, 0x000001, + 0x000001, 0x000003, 0x000006, 0x000003, 0x000003, 0x000009, 0x000010, 0x000002, 0x000004, 0x000010, 0x00a6dd, + 0x001034, 0x0000dd, 0x001681, 0x001d30, 0x00021d, 0x00134a +}; + +/** + * Non-interval characters for ID_Start. + */ +static const uint32_t lit_unicode_id_start_chars_sup[] JERRY_ATTR_CONST_DATA = { + 0x010808, 0x01083c, 0x010a00, 0x010f27, 0x011144, 0x011147, 0x011176, 0x0111da, 0x0111dc, 0x011288, 0x01133d, + 0x011350, 0x0114c7, 0x011644, 0x0116b8, 0x011909, 0x01193f, 0x011941, 0x0119e1, 0x0119e3, 0x011a00, 0x011a3a, + 0x011a50, 0x011a9d, 0x011c40, 0x011d46, 0x011d98, 0x011fb0, 0x016f50, 0x016fe3, 0x01d4a2, 0x01d4bb, 0x01d546, + 0x01e14e, 0x01e94b, 0x01ee24, 0x01ee27, 0x01ee39, 0x01ee3b, 0x01ee42, 0x01ee47, 0x01ee49, 0x01ee4b, 0x01ee54, + 0x01ee57, 0x01ee59, 0x01ee5b, 0x01ee5d, 0x01ee5f, 0x01ee64, 0x01ee7e +}; + +/** + * Character interval starting points for ID_Continue. + */ +static const uint32_t lit_unicode_id_continue_interval_starts_sup[] JERRY_ATTR_CONST_DATA = { + 0x010376, 0x0104a0, 0x010a01, 0x010a05, 0x010a0c, 0x010a38, 0x010ae5, 0x010d24, 0x010d30, 0x010eab, 0x010f46, + 0x011000, 0x011038, 0x011066, 0x01107f, 0x0110b0, 0x0110f0, 0x011100, 0x011127, 0x011136, 0x011145, 0x011180, + 0x0111b3, 0x0111c9, 0x0111ce, 0x01122c, 0x0112df, 0x0112f0, 0x011300, 0x01133b, 0x01133e, 0x011347, 0x01134b, + 0x011362, 0x011366, 0x011370, 0x011435, 0x011450, 0x0114b0, 0x0114d0, 0x0115af, 0x0115b8, 0x0115dc, 0x011630, + 0x011650, 0x0116ab, 0x0116c0, 0x01171d, 0x011730, 0x01182c, 0x0118e0, 0x011930, 0x011937, 0x01193b, 0x011942, + 0x011950, 0x0119d1, 0x0119da, 0x011a01, 0x011a33, 0x011a3b, 0x011a51, 0x011a8a, 0x011c2f, 0x011c38, 0x011c50, + 0x011c92, 0x011ca9, 0x011d31, 0x011d3c, 0x011d3f, 0x011d50, 0x011d8a, 0x011d90, 0x011d93, 0x011da0, 0x011ef3, + 0x016a60, 0x016af0, 0x016b30, 0x016b50, 0x016f51, 0x016f8f, 0x016ff0, 0x01bc9d, 0x01d165, 0x01d16d, 0x01d17b, + 0x01d185, 0x01d1aa, 0x01d242, 0x01d7ce, 0x01da00, 0x01da3b, 0x01da9b, 0x01daa1, 0x01e000, 0x01e008, 0x01e01b, + 0x01e023, 0x01e026, 0x01e130, 0x01e140, 0x01e2ec, 0x01e8d0, 0x01e944, 0x01e950, 0x01fbf0, 0x0e0100 +}; + +/** + * Character interval lengths for ID_Continue. + */ +static const uint16_t lit_unicode_id_continue_interval_lengths_sup[] JERRY_ATTR_CONST_DATA = { + 0x000004, 0x000009, 0x000002, 0x000001, 0x000003, 0x000002, 0x000001, 0x000003, 0x000009, 0x000001, 0x00000a, + 0x000002, 0x00000e, 0x000009, 0x000003, 0x00000a, 0x000009, 0x000002, 0x00000d, 0x000009, 0x000001, 0x000002, + 0x00000d, 0x000003, 0x00000b, 0x00000b, 0x00000b, 0x000009, 0x000003, 0x000001, 0x000006, 0x000001, 0x000002, + 0x000001, 0x000006, 0x000004, 0x000011, 0x000009, 0x000013, 0x000009, 0x000006, 0x000008, 0x000001, 0x000010, + 0x000009, 0x00000c, 0x000009, 0x00000e, 0x000009, 0x00000e, 0x000009, 0x000005, 0x000001, 0x000003, 0x000001, + 0x000009, 0x000006, 0x000006, 0x000009, 0x000006, 0x000003, 0x00000a, 0x00000f, 0x000007, 0x000007, 0x000009, + 0x000015, 0x00000d, 0x000005, 0x000001, 0x000006, 0x000009, 0x000004, 0x000001, 0x000004, 0x000009, 0x000003, + 0x000009, 0x000004, 0x000006, 0x000009, 0x000036, 0x000003, 0x000001, 0x000001, 0x000004, 0x000005, 0x000007, + 0x000006, 0x000003, 0x000002, 0x000031, 0x000036, 0x000031, 0x000004, 0x00000e, 0x000006, 0x000010, 0x000006, + 0x000001, 0x000004, 0x000006, 0x000009, 0x00000d, 0x000006, 0x000006, 0x000009, 0x000009, 0x0000ef +}; + +/** + * Non-interval characters for ID_Continue. + */ +static const uint32_t lit_unicode_id_continue_chars_sup[] JERRY_ATTR_CONST_DATA = { + 0x0101fd, 0x0102e0, 0x010a3f, 0x011173, 0x01123e, 0x011357, 0x01145e, 0x011940, + 0x0119e4, 0x011a47, 0x011d3a, 0x011d47, 0x016f4f, 0x016fe4, 0x01da75, 0x01da84 +}; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges.inc.h b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges.inc.h new file mode 100644 index 00000000..75022dd2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/lit-unicode-ranges.inc.h @@ -0,0 +1,176 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-unicode.py script + * from DerivedCoreProperties.txt. Do not edit! */ + +/** + * Character interval starting points for ID_Start. + */ +static const uint16_t lit_unicode_id_start_interval_starts[] JERRY_ATTR_CONST_DATA = { + 0x00c0, 0x00d8, 0x00f8, 0x01f8, 0x02c6, 0x02e0, 0x0370, 0x0376, 0x037a, 0x0388, 0x038e, 0x03a3, 0x03f7, 0x048a, + 0x0531, 0x0560, 0x05d0, 0x05ef, 0x0620, 0x066e, 0x0671, 0x06e5, 0x06ee, 0x06fa, 0x0712, 0x074d, 0x07ca, 0x07f4, + 0x0800, 0x0840, 0x0860, 0x08a0, 0x08b6, 0x0904, 0x0958, 0x0971, 0x0985, 0x098f, 0x0993, 0x09aa, 0x09b6, 0x09dc, + 0x09df, 0x09f0, 0x0a05, 0x0a0f, 0x0a13, 0x0a2a, 0x0a32, 0x0a35, 0x0a38, 0x0a59, 0x0a72, 0x0a85, 0x0a8f, 0x0a93, + 0x0aaa, 0x0ab2, 0x0ab5, 0x0ae0, 0x0b05, 0x0b0f, 0x0b13, 0x0b2a, 0x0b32, 0x0b35, 0x0b5c, 0x0b5f, 0x0b85, 0x0b8e, + 0x0b92, 0x0b99, 0x0b9e, 0x0ba3, 0x0ba8, 0x0bae, 0x0c05, 0x0c0e, 0x0c12, 0x0c2a, 0x0c58, 0x0c60, 0x0c85, 0x0c8e, + 0x0c92, 0x0caa, 0x0cb5, 0x0ce0, 0x0cf1, 0x0d04, 0x0d0e, 0x0d12, 0x0d54, 0x0d5f, 0x0d7a, 0x0d85, 0x0d9a, 0x0db3, + 0x0dc0, 0x0e01, 0x0e32, 0x0e40, 0x0e81, 0x0e86, 0x0e8c, 0x0ea7, 0x0eb2, 0x0ec0, 0x0edc, 0x0f40, 0x0f49, 0x0f88, + 0x1000, 0x1050, 0x105a, 0x1065, 0x106e, 0x1075, 0x10a0, 0x10d0, 0x10fc, 0x11fc, 0x124a, 0x1250, 0x125a, 0x1260, + 0x128a, 0x1290, 0x12b2, 0x12b8, 0x12c2, 0x12c8, 0x12d8, 0x1312, 0x1318, 0x1380, 0x13a0, 0x13f8, 0x1401, 0x1501, + 0x1601, 0x166f, 0x1681, 0x16a0, 0x16ee, 0x1700, 0x170e, 0x1720, 0x1740, 0x1760, 0x176e, 0x1780, 0x1820, 0x1880, + 0x18b0, 0x1900, 0x1950, 0x1970, 0x1980, 0x19b0, 0x1a00, 0x1a20, 0x1b05, 0x1b45, 0x1b83, 0x1bae, 0x1bba, 0x1c00, + 0x1c4d, 0x1c5a, 0x1c80, 0x1c90, 0x1cbd, 0x1ce9, 0x1cee, 0x1cf5, 0x1d00, 0x1e00, 0x1f00, 0x1f18, 0x1f20, 0x1f48, + 0x1f50, 0x1f5f, 0x1f80, 0x1fb6, 0x1fc2, 0x1fc6, 0x1fd0, 0x1fd6, 0x1fe0, 0x1ff2, 0x1ff6, 0x2090, 0x210a, 0x2118, + 0x212a, 0x213c, 0x2145, 0x2160, 0x2c00, 0x2c30, 0x2c60, 0x2ceb, 0x2cf2, 0x2d00, 0x2d30, 0x2d80, 0x2da0, 0x2da8, + 0x2db0, 0x2db8, 0x2dc0, 0x2dc8, 0x2dd0, 0x2dd8, 0x3005, 0x3021, 0x3031, 0x3038, 0x3041, 0x309b, 0x30a1, 0x30fc, + 0x3105, 0x3131, 0x31a0, 0x31f0, 0x3400, 0x3500, 0x3600, 0x3700, 0x3800, 0x3900, 0x3a00, 0x3b00, 0x3c00, 0x3d00, + 0x3e00, 0x3f00, 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4a00, 0x4b00, + 0x4c00, 0x4d00, 0x4e00, 0x4f00, 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, + 0x5a00, 0x5b00, 0x5c00, 0x5d00, 0x5e00, 0x5f00, 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, 0x6700, + 0x6800, 0x6900, 0x6a00, 0x6b00, 0x6c00, 0x6d00, 0x6e00, 0x6f00, 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, + 0x7600, 0x7700, 0x7800, 0x7900, 0x7a00, 0x7b00, 0x7c00, 0x7d00, 0x7e00, 0x7f00, 0x8000, 0x8100, 0x8200, 0x8300, + 0x8400, 0x8500, 0x8600, 0x8700, 0x8800, 0x8900, 0x8a00, 0x8b00, 0x8c00, 0x8d00, 0x8e00, 0x8f00, 0x9000, 0x9100, + 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, 0x9800, 0x9900, 0x9a00, 0x9b00, 0x9c00, 0x9d00, 0x9e00, 0x9f00, + 0xa000, 0xa100, 0xa200, 0xa300, 0xa400, 0xa4d0, 0xa500, 0xa600, 0xa610, 0xa62a, 0xa640, 0xa67f, 0xa6a0, 0xa717, + 0xa722, 0xa78b, 0xa7c2, 0xa7f5, 0xa803, 0xa807, 0xa80c, 0xa840, 0xa882, 0xa8f2, 0xa8fd, 0xa90a, 0xa930, 0xa960, + 0xa984, 0xa9e0, 0xa9e6, 0xa9fa, 0xaa00, 0xaa40, 0xaa44, 0xaa60, 0xaa7e, 0xaab5, 0xaab9, 0xaadb, 0xaae0, 0xaaf2, + 0xab01, 0xab09, 0xab11, 0xab20, 0xab28, 0xab30, 0xab5c, 0xab70, 0xac00, 0xad00, 0xae00, 0xaf00, 0xb000, 0xb100, + 0xb200, 0xb300, 0xb400, 0xb500, 0xb600, 0xb700, 0xb800, 0xb900, 0xba00, 0xbb00, 0xbc00, 0xbd00, 0xbe00, 0xbf00, + 0xc000, 0xc100, 0xc200, 0xc300, 0xc400, 0xc500, 0xc600, 0xc700, 0xc800, 0xc900, 0xca00, 0xcb00, 0xcc00, 0xcd00, + 0xce00, 0xcf00, 0xd000, 0xd100, 0xd200, 0xd300, 0xd400, 0xd500, 0xd600, 0xd700, 0xd7b0, 0xd7cb, 0xf900, 0xfa00, + 0xfa70, 0xfb00, 0xfb13, 0xfb1f, 0xfb2a, 0xfb38, 0xfb40, 0xfb43, 0xfb46, 0xfbd3, 0xfcd3, 0xfd50, 0xfd92, 0xfdf0, + 0xfe70, 0xfe76, 0xff21, 0xff41, 0xff66, 0xffc2, 0xffca, 0xffd2, 0xffda +}; + +/** + * Character interval lengths for ID_Start. + */ +static const uint8_t lit_unicode_id_start_interval_lengths[] JERRY_ATTR_CONST_DATA = { + 0x0016, 0x001e, 0x00ff, 0x00c9, 0x000b, 0x0004, 0x0004, 0x0001, 0x0003, 0x0002, 0x0013, 0x0052, 0x008a, 0x00a5, + 0x0025, 0x0028, 0x001a, 0x0003, 0x002a, 0x0001, 0x0062, 0x0001, 0x0001, 0x0002, 0x001d, 0x0058, 0x0020, 0x0001, + 0x0015, 0x0018, 0x000a, 0x0014, 0x0011, 0x0035, 0x0009, 0x000f, 0x0007, 0x0001, 0x0015, 0x0006, 0x0003, 0x0001, + 0x0002, 0x0001, 0x0005, 0x0001, 0x0015, 0x0006, 0x0001, 0x0001, 0x0001, 0x0003, 0x0002, 0x0008, 0x0002, 0x0015, + 0x0006, 0x0001, 0x0004, 0x0001, 0x0007, 0x0001, 0x0015, 0x0006, 0x0001, 0x0004, 0x0001, 0x0002, 0x0005, 0x0002, + 0x0003, 0x0001, 0x0001, 0x0001, 0x0002, 0x000b, 0x0007, 0x0002, 0x0016, 0x000f, 0x0002, 0x0001, 0x0007, 0x0002, + 0x0016, 0x0009, 0x0004, 0x0001, 0x0001, 0x0008, 0x0002, 0x0028, 0x0002, 0x0002, 0x0005, 0x0011, 0x0017, 0x0008, + 0x0006, 0x002f, 0x0001, 0x0006, 0x0001, 0x0004, 0x0017, 0x0009, 0x0001, 0x0004, 0x0003, 0x0007, 0x0023, 0x0004, + 0x002a, 0x0005, 0x0003, 0x0001, 0x0002, 0x000c, 0x0025, 0x002a, 0x00ff, 0x004c, 0x0003, 0x0006, 0x0003, 0x0028, + 0x0003, 0x0020, 0x0003, 0x0006, 0x0003, 0x000e, 0x0038, 0x0003, 0x0042, 0x000f, 0x0055, 0x0005, 0x00ff, 0x00ff, + 0x006b, 0x0010, 0x0019, 0x004a, 0x000a, 0x000c, 0x0003, 0x0011, 0x0011, 0x000c, 0x0002, 0x0033, 0x0058, 0x0028, + 0x0045, 0x001e, 0x001d, 0x0004, 0x002b, 0x0019, 0x0016, 0x0034, 0x002e, 0x0006, 0x001d, 0x0001, 0x002b, 0x0023, + 0x0002, 0x0023, 0x0008, 0x002a, 0x0002, 0x0003, 0x0005, 0x0001, 0x00bf, 0x00ff, 0x0015, 0x0005, 0x0025, 0x0005, + 0x0007, 0x001e, 0x0034, 0x0006, 0x0002, 0x0006, 0x0003, 0x0005, 0x000c, 0x0002, 0x0006, 0x000c, 0x0009, 0x0005, + 0x000f, 0x0003, 0x0004, 0x0028, 0x002e, 0x002e, 0x0084, 0x0003, 0x0001, 0x0025, 0x0037, 0x0016, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0002, 0x0008, 0x0004, 0x0004, 0x0055, 0x0004, 0x0059, 0x0003, + 0x002a, 0x005d, 0x001f, 0x000f, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00bf, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00fc, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x008c, 0x002d, 0x00ff, 0x000c, 0x000f, 0x0001, 0x002e, 0x001e, 0x004f, 0x0008, + 0x0066, 0x0034, 0x0008, 0x000c, 0x0002, 0x0003, 0x0016, 0x0033, 0x0031, 0x0005, 0x0001, 0x001b, 0x0016, 0x001c, + 0x002e, 0x0004, 0x0009, 0x0004, 0x0028, 0x0002, 0x0007, 0x0016, 0x0031, 0x0001, 0x0004, 0x0002, 0x000a, 0x0002, + 0x0005, 0x0005, 0x0005, 0x0006, 0x0006, 0x002a, 0x000d, 0x0072, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, + 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00a3, 0x0016, 0x0030, 0x00ff, 0x006d, + 0x0069, 0x0006, 0x0004, 0x0009, 0x000c, 0x0004, 0x0001, 0x0001, 0x006b, 0x00ff, 0x006a, 0x003f, 0x0035, 0x000b, + 0x0004, 0x0086, 0x0019, 0x0019, 0x0058, 0x0005, 0x0005, 0x0005, 0x0002 +}; + +/** + * Non-interval characters for ID_Start. + */ +static const uint16_t lit_unicode_id_start_chars[] JERRY_ATTR_CONST_DATA = { + 0x00aa, 0x00b5, 0x00ba, 0x02ec, 0x02ee, 0x037f, 0x0386, 0x038c, 0x0559, 0x06d5, 0x06ff, 0x0710, 0x07b1, 0x07fa, + 0x081a, 0x0824, 0x0828, 0x093d, 0x0950, 0x09b2, 0x09bd, 0x09ce, 0x09fc, 0x0a5e, 0x0abd, 0x0ad0, 0x0af9, 0x0b3d, + 0x0b71, 0x0b83, 0x0b9c, 0x0bd0, 0x0c3d, 0x0c80, 0x0cbd, 0x0cde, 0x0d3d, 0x0d4e, 0x0dbd, 0x0e84, 0x0ea5, 0x0ebd, + 0x0ec6, 0x0f00, 0x103f, 0x1061, 0x108e, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1cfa, + 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2d27, + 0x2d2d, 0x2d6f, 0xa8fb, 0xa9cf, 0xaa7a, 0xaab1, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e +}; + +/** + * Character interval starting points for ID_Continue. + */ +static const uint16_t lit_unicode_id_continue_interval_starts[] JERRY_ATTR_CONST_DATA = { + 0x0300, 0x0483, 0x0591, 0x05c1, 0x05c4, 0x0610, 0x064b, 0x06d6, 0x06df, 0x06e7, 0x06ea, 0x06f0, 0x0730, 0x07a6, + 0x07c0, 0x07eb, 0x0816, 0x081b, 0x0825, 0x0829, 0x0859, 0x08d3, 0x08e3, 0x093a, 0x093e, 0x0951, 0x0962, 0x0966, + 0x0981, 0x09be, 0x09c7, 0x09cb, 0x09e2, 0x09e6, 0x0a01, 0x0a3e, 0x0a47, 0x0a4b, 0x0a66, 0x0a81, 0x0abe, 0x0ac7, + 0x0acb, 0x0ae2, 0x0ae6, 0x0afa, 0x0b01, 0x0b3e, 0x0b47, 0x0b4b, 0x0b55, 0x0b62, 0x0b66, 0x0bbe, 0x0bc6, 0x0bca, + 0x0be6, 0x0c00, 0x0c3e, 0x0c46, 0x0c4a, 0x0c55, 0x0c62, 0x0c66, 0x0c81, 0x0cbe, 0x0cc6, 0x0cca, 0x0cd5, 0x0ce2, + 0x0ce6, 0x0d00, 0x0d3b, 0x0d3e, 0x0d46, 0x0d4a, 0x0d62, 0x0d66, 0x0d81, 0x0dcf, 0x0dd8, 0x0de6, 0x0df2, 0x0e34, + 0x0e47, 0x0e50, 0x0eb4, 0x0ec8, 0x0ed0, 0x0f18, 0x0f20, 0x0f3e, 0x0f71, 0x0f86, 0x0f8d, 0x0f99, 0x102b, 0x1040, + 0x1056, 0x105e, 0x1062, 0x1067, 0x1071, 0x1082, 0x108f, 0x135d, 0x1369, 0x1712, 0x1732, 0x1752, 0x1772, 0x17b4, + 0x17e0, 0x180b, 0x1810, 0x1920, 0x1930, 0x1946, 0x19d0, 0x1a17, 0x1a55, 0x1a60, 0x1a7f, 0x1a90, 0x1ab0, 0x1abf, + 0x1b00, 0x1b34, 0x1b50, 0x1b6b, 0x1b80, 0x1ba1, 0x1bb0, 0x1be6, 0x1c24, 0x1c40, 0x1c50, 0x1cd0, 0x1cd4, 0x1cf7, + 0x1dc0, 0x1dfb, 0x200c, 0x203f, 0x20d0, 0x20e5, 0x2cef, 0x2de0, 0x302a, 0x3099, 0xa620, 0xa674, 0xa69e, 0xa6f0, + 0xa823, 0xa880, 0xa8b4, 0xa8d0, 0xa8e0, 0xa8ff, 0xa926, 0xa947, 0xa980, 0xa9b3, 0xa9d0, 0xa9f0, 0xaa29, 0xaa4c, + 0xaa50, 0xaa7b, 0xaab2, 0xaab7, 0xaabe, 0xaaeb, 0xaaf5, 0xabe3, 0xabec, 0xabf0, 0xfe00, 0xfe20, 0xfe33, 0xfe4d, + 0xff10 +}; + +/** + * Character interval lengths for ID_Continue. + */ +static const uint8_t lit_unicode_id_continue_interval_lengths[] JERRY_ATTR_CONST_DATA = { + 0x006f, 0x0004, 0x002c, 0x0001, 0x0001, 0x000a, 0x001e, 0x0006, 0x0005, 0x0001, 0x0003, 0x0009, 0x001a, 0x000a, + 0x0009, 0x0008, 0x0003, 0x0008, 0x0002, 0x0004, 0x0002, 0x000e, 0x0020, 0x0002, 0x0011, 0x0006, 0x0001, 0x0009, + 0x0002, 0x0006, 0x0001, 0x0002, 0x0001, 0x0009, 0x0002, 0x0004, 0x0001, 0x0002, 0x000b, 0x0002, 0x0007, 0x0002, + 0x0002, 0x0001, 0x0009, 0x0005, 0x0002, 0x0006, 0x0001, 0x0002, 0x0002, 0x0001, 0x0009, 0x0004, 0x0002, 0x0003, + 0x0009, 0x0004, 0x0006, 0x0002, 0x0003, 0x0001, 0x0001, 0x0009, 0x0002, 0x0006, 0x0002, 0x0003, 0x0001, 0x0001, + 0x0009, 0x0003, 0x0001, 0x0006, 0x0002, 0x0003, 0x0001, 0x0009, 0x0002, 0x0005, 0x0007, 0x0009, 0x0001, 0x0006, + 0x0007, 0x0009, 0x0008, 0x0005, 0x0009, 0x0001, 0x0009, 0x0001, 0x0013, 0x0001, 0x000a, 0x0023, 0x0013, 0x0009, + 0x0003, 0x0002, 0x0002, 0x0006, 0x0003, 0x000b, 0x000e, 0x0002, 0x0008, 0x0002, 0x0002, 0x0001, 0x0001, 0x001f, + 0x0009, 0x0002, 0x0009, 0x000b, 0x000b, 0x0009, 0x000a, 0x0004, 0x0009, 0x001c, 0x000a, 0x0009, 0x000d, 0x0001, + 0x0004, 0x0010, 0x0009, 0x0008, 0x0002, 0x000c, 0x0009, 0x000d, 0x0013, 0x0009, 0x0009, 0x0002, 0x0014, 0x0002, + 0x0039, 0x0004, 0x0001, 0x0001, 0x000c, 0x000b, 0x0002, 0x001f, 0x0005, 0x0001, 0x0009, 0x0009, 0x0001, 0x0001, + 0x0004, 0x0001, 0x0011, 0x0009, 0x0011, 0x000a, 0x0007, 0x000c, 0x0003, 0x000d, 0x0009, 0x0009, 0x000d, 0x0001, + 0x0009, 0x0002, 0x0002, 0x0001, 0x0001, 0x0004, 0x0001, 0x0007, 0x0001, 0x0009, 0x000f, 0x000f, 0x0001, 0x0002, + 0x0009 +}; + +/** + * Non-interval characters for ID_Continue. + */ +static const uint16_t lit_unicode_id_continue_chars[] JERRY_ATTR_CONST_DATA = { + 0x00b7, 0x0387, 0x05bf, 0x05c7, 0x0670, 0x0711, 0x07fd, 0x09bc, 0x09d7, 0x09fe, 0x0a3c, 0x0a51, + 0x0a75, 0x0abc, 0x0b3c, 0x0b82, 0x0bd7, 0x0cbc, 0x0d57, 0x0dca, 0x0dd6, 0x0e31, 0x0eb1, 0x0f35, + 0x0f37, 0x0f39, 0x0fc6, 0x17dd, 0x18a9, 0x1ced, 0x1cf4, 0x2054, 0x20e1, 0x2d7f, 0xa66f, 0xa802, + 0xa806, 0xa80b, 0xa82c, 0xa9e5, 0xaa43, 0xaab0, 0xaac1, 0xfb1e, 0xff3f +}; + +/** + * Character interval starting points for White_Space. + */ +static const uint16_t lit_unicode_white_space_interval_starts[] JERRY_ATTR_CONST_DATA = { 0x2000 }; + +/** + * Character interval lengths for White_Space. + */ +static const uint8_t lit_unicode_white_space_interval_lengths[] JERRY_ATTR_CONST_DATA = { 0x000a }; + +/** + * Non-interval characters for White_Space. + */ +static const uint16_t lit_unicode_white_space_chars[] JERRY_ATTR_CONST_DATA = { 0x00a0, + 0x1680, + 0x202f, + 0x205f, + 0x3000 }; diff --git a/src/loaders/lottie/jerryscript/jerry-core/lit/meson.build b/src/loaders/lottie/jerryscript/jerry-core/lit/meson.build new file mode 100644 index 00000000..83faa5f2 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/lit/meson.build @@ -0,0 +1,20 @@ +source_file = [ + 'lit-char-helpers.h', + 'lit-globals.h', + 'lit-magic-strings.h', + 'lit-magic-strings.inc.h', + 'lit-strings.h', + 'lit-unicode-conversions-sup.inc.h', + 'lit-unicode-conversions.inc.h', + 'lit-unicode-folding.inc.h', + 'lit-unicode-ranges-sup.inc.h', + 'lit-unicode-ranges.inc.h', + 'lit-char-helpers.cpp', + 'lit-magic-strings.cpp', + 'lit-strings.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/meson.build b/src/loaders/lottie/jerryscript/jerry-core/meson.build new file mode 100644 index 00000000..adbbffbb --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/meson.build @@ -0,0 +1,9 @@ +subdir('api') +subdir('include') +subdir('ecma') +subdir('jcontext') +subdir('jmem') +subdir('jrt') +subdir('lit') +subdir('parser') +subdir('vm') diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.cpp new file mode 100644 index 00000000..d2c4fc10 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.cpp @@ -0,0 +1,86 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +/* These two checks only checks the compiler, they have no effect on the code. */ +JERRY_STATIC_ASSERT ((sizeof (cbc_uint8_arguments_t) == 16), sizeof_cbc_uint8_arguments_t_must_be_16_byte_long); + +JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) == 24), sizeof_cbc_uint16_arguments_t_must_be_24_byte_long); + +JERRY_STATIC_ASSERT ((offsetof (cbc_uint8_arguments_t, script_value) == offsetof (cbc_uint16_arguments_t, script_value)), + script_value_in_cbc_uint8_arguments_and_cbc_uint16_arguments_must_be_in_the_same_offset); + +/** + * The reason of these two static asserts to notify the developer to increase the JERRY_SNAPSHOT_VERSION + * whenever new bytecodes are introduced or existing ones have been deleted. + */ +JERRY_STATIC_ASSERT ((((int) CBC_END) == 238), number_of_cbc_opcodes_changed); +JERRY_STATIC_ASSERT ((((int) CBC_EXT_END) == 167), number_of_cbc_ext_opcodes_changed); + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_bytecode Bytecode + * @{ + */ + +#if JERRY_PARSER || JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Compact bytecode definition + */ +#define CBC_OPCODE(arg1, arg2, arg3, arg4) ((arg2) | (((arg3) + CBC_STACK_ADJUST_BASE) << CBC_STACK_ADJUST_SHIFT)), + +/** + * Flags of the opcodes. + */ +const uint8_t cbc_flags[] JERRY_ATTR_CONST_DATA = { CBC_OPCODE_LIST }; + +/** + * Flags of the extended opcodes. + */ +const uint8_t cbc_ext_flags[] = { CBC_EXT_OPCODE_LIST }; + +#undef CBC_OPCODE + +#endif /* JERRY_PARSER || JERRY_PARSER_DUMP_BYTE_CODE */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + +#define CBC_OPCODE(arg1, arg2, arg3, arg4) #arg1, + +/** + * Names of the opcodes. + */ +const char* const cbc_names[] = { CBC_OPCODE_LIST }; + +/** + * Names of the extended opcodes. + */ +const char* const cbc_ext_names[] = { CBC_EXT_OPCODE_LIST }; + +#undef CBC_OPCODE + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.h new file mode 100644 index 00000000..0c627ec7 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/byte-code.h @@ -0,0 +1,1054 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BYTE_CODE_H +#define BYTE_CODE_H + +#include "ecma-globals.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_bytecode Bytecode + * @{ + */ + +/** + * Compact byte code (CBC) is a byte code representation + * of EcmaScript which is designed for low memory + * environments. Most opcodes are only one or sometimes + * two byte long so the CBC provides a small binary size. + * + * The execution engine of CBC is a stack machine, where + * the maximum stack size is known in advance for each + * function. + */ + +/** + * Byte code flags. Only the lower 5 bit can be used + * since the stack change is encoded in the upper + * three bits for each instruction between -4 and 3 + * (except for call / construct opcodes). + */ +#define CBC_STACK_ADJUST_BASE 4 +#define CBC_STACK_ADJUST_SHIFT 5 +#define CBC_STACK_ADJUST_VALUE(value) (((value) >> CBC_STACK_ADJUST_SHIFT) - CBC_STACK_ADJUST_BASE) + +#define CBC_NO_FLAG 0x00u +#define CBC_HAS_LITERAL_ARG 0x01u +#define CBC_HAS_LITERAL_ARG2 0x02u +#define CBC_HAS_BYTE_ARG 0x04u +#define CBC_HAS_BRANCH_ARG 0x08u + +/* These flags are shared */ +#define CBC_FORWARD_BRANCH_ARG 0x10u +#define CBC_POP_STACK_BYTE_ARG 0x10u + +#define CBC_ARG_TYPES (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2 | CBC_HAS_BYTE_ARG | CBC_HAS_BRANCH_ARG) + +#define CBC_HAS_POP_STACK_BYTE_ARG (CBC_HAS_BYTE_ARG | CBC_POP_STACK_BYTE_ARG) + +/** + * CBC_NO_RESULT_OPERATION for ext opcodes + */ +#define CBC_EXT_NO_RESULT_OPERATION(opcode) \ + ((opcode) >= PARSER_TO_EXT_OPCODE (CBC_EXT_ASSIGN_SUPER) \ + && (opcode) <= PARSER_TO_EXT_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK)) + +/* Debug macro. */ +#define CBC_ARGS_EQ(op, types) ((cbc_flags[op] & CBC_ARG_TYPES) == (types)) + +/* Debug macro. */ +#define CBC_SAME_ARGS(op1, op2) \ + (CBC_EXT_NO_RESULT_OPERATION (op1) ? ((cbc_ext_flags[PARSER_GET_EXT_OPCODE (op1)] & CBC_ARG_TYPES) \ + == (cbc_ext_flags[PARSER_GET_EXT_OPCODE (op2)] & CBC_ARG_TYPES)) \ + : ((cbc_flags[op1] & CBC_ARG_TYPES) == (cbc_flags[op2] & CBC_ARG_TYPES))) + +#define CBC_UNARY_OPERATION(name, group) \ + CBC_OPCODE (name, CBC_NO_FLAG, 0, (VM_OC_##group) | VM_OC_GET_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_LITERAL, CBC_HAS_LITERAL_ARG, 1, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) + +#define CBC_BINARY_OPERATION(name, group) \ + CBC_OPCODE (name, CBC_NO_FLAG, -1, (VM_OC_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_RIGHT_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + (VM_OC_##group) | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_TWO_LITERALS, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + (VM_OC_##group) | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) + +#define CBC_UNARY_LVALUE_OPERATION(name, group) \ + CBC_OPCODE (name, CBC_NO_FLAG, -2, (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (name##_PUSH_RESULT, \ + CBC_NO_FLAG, \ + -1, \ + (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_BLOCK, \ + CBC_NO_FLAG, \ + -2, \ + (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (name##_IDENT, CBC_HAS_LITERAL_ARG, 0, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ + CBC_OPCODE (name##_IDENT_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ + CBC_OPCODE (name##_IDENT_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) + +#define CBC_UNARY_LVALUE_WITH_IDENT 3 + +#define CBC_BINARY_WITH_LITERAL 1 +#define CBC_BINARY_WITH_TWO_LITERALS 2 + +/** + * Several opcodes (mostly call and assignment opcodes) have + * two forms: one which does not push a return value onto + * the stack, and another which does. The reason is that + * the return value of these opcodes are often not used + * and the first form provides smaller byte code. + * + * The following rules must be kept by the code generator: + * - only the opcode without return value can be emitted + * by the code generator + * - the first form can be converted to the second form + * by adding 1 to the opcode + * - after the conversion the opcode must be immediately + * flushed, so no further changes are possible + * + * Hence CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode) + * cannot be true for an opcode which has a result + */ +#define CBC_NO_RESULT_OPERATION(opcode) \ + (((opcode) >= CBC_PRE_INCR && (opcode) < CBC_END) || CBC_EXT_NO_RESULT_OPERATION ((opcode))) + +/** + * Branch instructions are organized in group of 8 opcodes. + * - 1st opcode: unused, can be used for other purpose + * - 2nd opcode: forward branch with 1 byte offset + * - 3rd opcode: forward branch with 2 byte offset + * - 4th opcode: forward branch with 3 byte offset + * - 5th opcode: unused, can be used for other purpose + * - 6th opcode: backward branch with 1 byte offset + * - 7th opcode: backward branch with 2 byte offset + * - 8th opcode: backward branch with 3 byte offset + * + * Reasons: + * The branch_opcode & 0x3 tells the length in bytes of the offset + * If branch offset & 0x4 == 0, it is a forward branch. Otherwise + * it is backward. + * + * The offset bytes are encoded in higher to lower order. + */ + +#define CBC_FORWARD_BRANCH(name, stack, vm_oc) \ + CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) \ + CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) \ + CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) + +#define CBC_BACKWARD_BRANCH(name, stack, vm_oc) \ + CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \ + CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \ + CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) + +#define CBC_BRANCH_OFFSET_LENGTH(opcode) ((opcode) &0x3) + +#define CBC_BRANCH_IS_BACKWARD(flags) (!((flags) &CBC_FORWARD_BRANCH_ARG)) + +#define CBC_BRANCH_IS_FORWARD(flags) ((flags) &CBC_FORWARD_BRANCH_ARG) + +/* Stack consumption of opcodes with context. */ + +/* PARSER_TRY_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_TRY_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_FINALLY_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_FINALLY_CONTEXT_STACK_ALLOCATION 2 +/* PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION 4 +/* PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION 4 +/* PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION 4 +/* PARSER_WITH_CONTEXT_STACK_ALLOCATION must be <= 4 */ +#define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_BLOCK_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION must be <= 3 */ +#define PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION 3 +/* PARSER_OBJECT_INITIALIZER_CONTEXT_STACK_ALLOCATION must be <= 2 */ +#define PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION 1 +/* PARSER_OBJECT_INITIALIZER_CONTEXT_STACK_ALLOCATION must be <= 2 */ +#define PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION 2 + +/** + * Extra stack consumption for finally context. + */ +#define PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION \ + (PARSER_FINALLY_CONTEXT_STACK_ALLOCATION - PARSER_TRY_CONTEXT_STACK_ALLOCATION) + +#define PARSER_STATIC_PRIVATE_TO_PRIVATE_OFFSET (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD - CBC_EXT_COLLECT_PRIVATE_FIELD) + +/** + * Opcode definitions. + */ +#define CBC_OPCODE_LIST \ + /* Branch opcodes first. Some other opcodes are mixed. */ \ + CBC_OPCODE (CBC_EXT_OPCODE, CBC_NO_FLAG, 0, VM_OC_NONE) \ + CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD, 0, VM_OC_JUMP) \ + CBC_OPCODE (CBC_POP, CBC_NO_FLAG, -1, VM_OC_POP) \ + CBC_BACKWARD_BRANCH (CBC_JUMP_BACKWARD, 0, VM_OC_JUMP) \ + CBC_OPCODE (CBC_POP_BLOCK, CBC_NO_FLAG, -1, VM_OC_POP_BLOCK | VM_OC_PUT_BLOCK) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD, -1, VM_OC_BRANCH_IF_TRUE) \ + CBC_OPCODE (CBC_THROW, CBC_NO_FLAG, -1, VM_OC_THROW | VM_OC_GET_STACK) \ + CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD, -1, VM_OC_BRANCH_IF_TRUE) \ + CBC_OPCODE (CBC_CONTEXT_END, CBC_NO_FLAG, 0, VM_OC_CONTEXT_END) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD, -1, VM_OC_BRANCH_IF_FALSE) \ + CBC_OPCODE (CBC_CREATE_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_OBJECT | VM_OC_PUT_STACK) \ + CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD, -1, VM_OC_BRANCH_IF_FALSE) \ + CBC_OPCODE (CBC_SET_PROPERTY, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ + CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT, 0, VM_OC_JUMP_AND_EXIT_CONTEXT) \ + CBC_OPCODE (CBC_CREATE_ARRAY, CBC_NO_FLAG, 1, VM_OC_PUSH_ARRAY | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1, VM_OC_BRANCH_IF_LOGICAL_TRUE) \ + CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1, VM_OC_BRANCH_IF_LOGICAL_FALSE) \ + CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1, VM_OC_PUSH_ELISON | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1, VM_OC_BRANCH_IF_STRICT_EQUAL) \ + CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION, VM_OC_BLOCK_CREATE_CONTEXT) \ + \ + /* Basic opcodes. Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_TWO_LITERALS, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 2, \ + VM_OC_PUSH_TWO | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_PUSH_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 2, VM_OC_PUSH_TWO | VM_OC_GET_THIS_LITERAL) \ + CBC_OPCODE (CBC_PUSH_THREE_LITERALS, CBC_HAS_LITERAL_ARG2, 3, VM_OC_PUSH_THREE | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_PUSH_UNDEFINED, CBC_NO_FLAG, 1, VM_OC_PUSH_UNDEFINED | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_TRUE, CBC_NO_FLAG, 1, VM_OC_PUSH_TRUE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1, VM_OC_PUSH_FALSE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1, VM_OC_PUSH_THIS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1, VM_OC_PUSH_0 | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_NUMBER_POS_BYTE, CBC_HAS_BYTE_ARG, 1, VM_OC_PUSH_POS_BYTE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_NUMBER_NEG_BYTE, CBC_HAS_BYTE_ARG, 1, VM_OC_PUSH_NEG_BYTE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2, VM_OC_PUSH_LIT_0 | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, \ + 2, \ + VM_OC_PUSH_LIT_POS_BYTE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, \ + 2, \ + VM_OC_PUSH_LIT_NEG_BYTE | VM_OC_GET_LITERAL) \ + /* Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_PROP, CBC_NO_FLAG, -1, VM_OC_PROP_GET | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_PROP_GET | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_PROP_GET | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_IDENT_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_IDENT_REFERENCE | VM_OC_PUT_STACK) \ + /* Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_PROP_REFERENCE, CBC_NO_FLAG, 1, VM_OC_PROP_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 2, \ + VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 3, \ + VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 3, \ + VM_OC_PROP_REFERENCE | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_NEW | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, VM_OC_NEW | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, VM_OC_NEW | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, VM_OC_EVAL) \ + CBC_OPCODE (CBC_CHECK_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_VAR) \ + CBC_OPCODE (CBC_CHECK_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_LET) \ + CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ + CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING) \ + CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING) \ + CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1, VM_OC_INIT_BINDING) \ + CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_INIT_ARG_OR_FUNC) \ + CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_VAR_EVAL) \ + CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_VAR_EVAL) \ + CBC_OPCODE (CBC_SET_VAR_FUNC, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, VM_OC_SET_BYTECODE_PTR) \ + CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, VM_OC_RETURN | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_RETURN_FUNCTION_END, CBC_NO_FLAG, 0, VM_OC_RETURN_FUNCTION_END) \ + CBC_OPCODE (CBC_RETURN_WITH_LITERAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_RETURN | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_SET_LITERAL_PROPERTY, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_COPY_TO_GLOBAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COPY_TO_GLOBAL | VM_OC_GET_LITERAL) \ + \ + /* Unary opcodes. */ \ + CBC_UNARY_OPERATION (CBC_PLUS, PLUS) \ + CBC_UNARY_OPERATION (CBC_NEGATE, MINUS) \ + CBC_UNARY_OPERATION (CBC_LOGICAL_NOT, NOT) \ + CBC_UNARY_OPERATION (CBC_BIT_NOT, BIT_NOT) \ + CBC_UNARY_OPERATION (CBC_VOID, VOID) \ + CBC_OPCODE (CBC_TYPEOF, CBC_NO_FLAG, 0, VM_OC_TYPEOF | VM_OC_GET_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_TYPEOF_IDENT, CBC_HAS_LITERAL_ARG, 1, VM_OC_TYPEOF_IDENT | VM_OC_PUT_STACK) \ + \ + /* Binary opcodes. */ \ + CBC_BINARY_OPERATION (CBC_BIT_OR, BIT_OR) \ + CBC_BINARY_OPERATION (CBC_BIT_XOR, BIT_XOR) \ + CBC_BINARY_OPERATION (CBC_BIT_AND, BIT_AND) \ + CBC_BINARY_OPERATION (CBC_EQUAL, EQUAL) \ + CBC_BINARY_OPERATION (CBC_NOT_EQUAL, NOT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_STRICT_EQUAL, STRICT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_STRICT_NOT_EQUAL, STRICT_NOT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_LESS, LESS) \ + CBC_BINARY_OPERATION (CBC_GREATER, GREATER) \ + CBC_BINARY_OPERATION (CBC_LESS_EQUAL, LESS_EQUAL) \ + CBC_BINARY_OPERATION (CBC_GREATER_EQUAL, GREATER_EQUAL) \ + CBC_BINARY_OPERATION (CBC_IN, IN) \ + CBC_BINARY_OPERATION (CBC_INSTANCEOF, INSTANCEOF) \ + CBC_BINARY_OPERATION (CBC_LEFT_SHIFT, LEFT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_RIGHT_SHIFT, RIGHT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_UNS_RIGHT_SHIFT, UNS_RIGHT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_ADD, ADD) \ + CBC_BINARY_OPERATION (CBC_SUBTRACT, SUB) \ + CBC_BINARY_OPERATION (CBC_MULTIPLY, MUL) \ + CBC_BINARY_OPERATION (CBC_DIVIDE, DIV) \ + CBC_BINARY_OPERATION (CBC_MODULO, MOD) \ + CBC_BINARY_OPERATION (CBC_EXPONENTIATION, EXP) \ + \ + /* Unary lvalue opcodes. */ \ + CBC_OPCODE (CBC_DELETE_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_PROP_DELETE | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_DELETE_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1, VM_OC_DELETE | VM_OC_PUT_STACK) \ + CBC_UNARY_LVALUE_OPERATION (CBC_PRE_INCR, PRE_INCR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_PRE_DECR, PRE_DECR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_POST_INCR, POST_INCR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_POST_DECR, POST_DECR) \ + \ + /* Call opcodes. */ \ + CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4, VM_OC_CALL) \ + CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK) \ + \ + /* Binary assignment opcodes. */ \ + CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_ASSIGN_PUSH_RESULT, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_BLOCK, \ + CBC_NO_FLAG, \ + -3, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT, CBC_HAS_LITERAL_ARG, -1, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_BLOCK, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + -2, \ + VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + -2, \ + VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_PUSH_RESULT, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_MOV_IDENT, CBC_HAS_LITERAL_ARG, -1, VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \ + CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_ASSIGN_LET_CONST | VM_OC_GET_LITERAL) \ + \ + /* Last opcode (not a real opcode). */ \ + CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, VM_OC_NONE) + +/* All EXT branches are statement block end + * marks, so they are always forward branches. */ + +#define CBC_EXT_OPCODE_LIST \ + /* Branch opcodes first. Some other opcodes are mixed. */ \ + CBC_OPCODE (CBC_EXT_NOP, CBC_NO_FLAG, 0, VM_OC_NONE) \ + CBC_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT, -1 + PARSER_WITH_CONTEXT_STACK_ALLOCATION, VM_OC_WITH) \ + CBC_OPCODE (CBC_EXT_FOR_IN_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_IN_GET_NEXT | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT, -1 + PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_IN_INIT) \ + CBC_OPCODE (CBC_EXT_SET_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT, 0, VM_OC_FOR_IN_HAS_NEXT) \ + CBC_OPCODE (CBC_EXT_FOR_OF_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_OF_GET_NEXT | VM_OC_PUT_STACK) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT, -1 + PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_OF_INIT) \ + CBC_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_PUSH_NAMED_FUNC_EXPR | VM_OC_GET_LITERAL_LITERAL) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT, 0, VM_OC_FOR_OF_HAS_NEXT) \ + CBC_OPCODE (CBC_EXT_CLONE_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT, \ + -1 + PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION, \ + VM_OC_FOR_AWAIT_OF_INIT) \ + CBC_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT, 0, VM_OC_FOR_AWAIT_OF_HAS_NEXT) \ + CBC_OPCODE (CBC_EXT_SET_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ + CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION, VM_OC_TRY) \ + CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0, VM_OC_BLOCK_CREATE_CONTEXT) \ + CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1, VM_OC_CATCH) \ + CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, VM_OC_RESOLVE_BASE_FOR_CALL) \ + CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION, VM_OC_FINALLY) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_PROP) \ + CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, VM_OC_DEFAULT_INITIALIZER) \ + CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0, VM_OC_ERROR) \ + CBC_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH, -1, VM_OC_BRANCH_IF_NULLISH) \ + \ + /* Basic opcodes. */ \ + CBC_OPCODE (CBC_EXT_POP_REFERENCE, CBC_NO_FLAG, -2, VM_OC_POP_REFERENCE) \ + CBC_OPCODE (CBC_EXT_CREATE_ARGUMENTS, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_ARGUMENTS) \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_EXT_VAR_EVAL) \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, VM_OC_EXT_VAR_EVAL) \ + CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0, VM_OC_COPY_FROM_ARG) \ + CBC_OPCODE (CBC_EXT_PUSH_REST_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_REST_OBJECT) \ + CBC_OPCODE (CBC_EXT_MODULE_IMPORT, CBC_NO_FLAG, 0, VM_OC_MODULE_IMPORT) \ + CBC_OPCODE (CBC_EXT_MODULE_IMPORT_META, CBC_NO_FLAG, 1, VM_OC_MODULE_IMPORT_META) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_STRING_CONCAT | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 1, \ + VM_OC_STRING_CONCAT | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1, VM_OC_GET_TEMPLATE_OBJECT | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, VM_OC_THROW_REFERENCE_ERROR) \ + CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0, VM_OC_THROW_CONST_ERROR) \ + CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0, VM_OC_REQUIRE_OBJECT_COERCIBLE) \ + CBC_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES, CBC_NO_FLAG, -1, VM_OC_COPY_DATA_PROPERTIES) \ + CBC_OPCODE (CBC_EXT_SET_FUNCTION_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_CLASS_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ + \ + /* Computed / class property related opcodes. */ \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + -1, \ + VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY, CBC_HAS_LITERAL_ARG, -1, VM_OC_SET_PROPERTY | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY, \ + CBC_NO_FLAG, \ + -2, \ + VM_OC_SET_COMPUTED_PROPERTY | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_GETTER | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_SET_SETTER | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_NO_FLAG, -2, VM_OC_SET_GETTER | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_NO_FLAG, -2, VM_OC_SET_SETTER | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, VM_OC_SET__PROTO__ | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_STATIC_FIELD_FUNC, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_ADD_STATIC_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_CLASS_CALL_STATIC_BLOCK, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_CLASS_CALL_STATIC_BLOCK | VM_OC_GET_LITERAL) \ + /* Class private property related opcodes */ \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 2, \ + VM_OC_PRIVATE_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PRIVATE_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_PRIVATE_IN | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PRIVATE_FIELD_ADD, CBC_HAS_LITERAL_ARG, -1, VM_OC_PRIVATE_FIELD_ADD | VM_OC_GET_STACK_LITERAL) \ + /* These 8 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_FIELD, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD, \ + CBC_HAS_LITERAL_ARG, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER, \ + CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ + 0, \ + VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ + /* Class related opcodes. */ \ + CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH_CLASS_ENVIRONMENT) \ + CBC_OPCODE (CBC_EXT_DEFINE_FIELD, CBC_HAS_LITERAL_ARG, -1, VM_OC_DEFINE_FIELD | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_INIT_CLASS, CBC_NO_FLAG, 0, VM_OC_INIT_CLASS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS, CBC_HAS_LITERAL_ARG, -2, VM_OC_FINALIZE_CLASS) \ + CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2, VM_OC_FINALIZE_CLASS) \ + CBC_OPCODE (CBC_EXT_SET_FIELD_INIT, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FIELD_INIT | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_RUN_FIELD_INIT, CBC_NO_FLAG, 0, VM_OC_RUN_FIELD_INIT) \ + CBC_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT, CBC_NO_FLAG, -1, VM_OC_RUN_STATIC_FIELD_INIT) \ + CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC, \ + CBC_NO_FLAG, \ + -1, \ + VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1, VM_OC_NONE) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_SUPER_CONSTRUCTOR) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE, \ + CBC_HAS_LITERAL_ARG, \ + 2, \ + VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT) \ + CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT) \ + CBC_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, 1, VM_OC_OBJECT_LITERAL_HOME_ENV) \ + CBC_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, -1, VM_OC_OBJECT_LITERAL_HOME_ENV) \ + CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1, VM_OC_RESOLVE_LEXICAL_THIS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_LOCAL_EVAL, CBC_HAS_BYTE_ARG, 0, VM_OC_LOCAL_EVAL) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER, CBC_NO_FLAG, -3, VM_OC_ASSIGN_SUPER) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_ASSIGN_SUPER | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3, VM_OC_ASSIGN_SUPER | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_ASSIGN_PRIVATE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_PUSH_RESULT, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + 0, \ + VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \ + \ + /* Spread / rest operation related opcodes. */ \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PUSH_RESULT, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + 0, \ + VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_SPREAD_ARGUMENTS) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_PUSH_RESULT, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + -2, \ + VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK, \ + CBC_HAS_POP_STACK_BYTE_ARG, \ + -3, \ + VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \ + CBC_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT, CBC_NO_FLAG, 1, VM_OC_PUSH_SPREAD_ELEMENT) \ + CBC_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY) \ + CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1, VM_OC_REST_INITIALIZER) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ + \ + /* Iterator related opcodes. */ \ + CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE, \ + CBC_NO_FLAG, \ + PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \ + VM_OC_ITERATOR_CONTEXT_CREATE) \ + CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END, \ + CBC_NO_FLAG, \ + -PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \ + VM_OC_ITERATOR_CONTEXT_END) \ + CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, VM_OC_ITERATOR_STEP) \ + \ + /* Object initializer related opcodes. */ \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE, \ + CBC_NO_FLAG, \ + PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \ + VM_OC_OBJ_INIT_CONTEXT_CREATE) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE, \ + CBC_NO_FLAG, \ + PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION, \ + VM_OC_OBJ_INIT_CONTEXT_CREATE) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST, CBC_NO_FLAG, 1, VM_OC_OBJ_INIT_PUSH_REST) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END, \ + CBC_NO_FLAG, \ + -PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \ + VM_OC_OBJ_INIT_CONTEXT_END) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, \ + CBC_HAS_LITERAL_ARG, \ + 1, \ + VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_LITERAL) \ + \ + /* Executable object related opcodes. */ \ + CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1, VM_OC_CREATE_GENERATOR) \ + CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0, VM_OC_YIELD) \ + CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_YIELD) \ + CBC_OPCODE (CBC_EXT_ASYNC_YIELD, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD) \ + CBC_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD_ITERATOR) \ + CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0, VM_OC_AWAIT) \ + CBC_OPCODE (CBC_EXT_GENERATOR_AWAIT, CBC_NO_FLAG, 0, VM_OC_GENERATOR_AWAIT) \ + CBC_OPCODE (CBC_EXT_ASYNC_EXIT, CBC_NO_FLAG, 0, VM_OC_ASYNC_EXIT) \ + CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1, VM_OC_EXT_RETURN | VM_OC_GET_STACK) \ + CBC_OPCODE (CBC_EXT_RETURN_UNDEFINED, CBC_NO_FLAG, 0, VM_OC_EXT_RETURN) \ + CBC_OPCODE (CBC_EXT_PUSH_NEW_TARGET, CBC_NO_FLAG, 1, VM_OC_PUSH_NEW_TARGET | VM_OC_PUT_STACK) \ + \ + /* Last opcode (not a real opcode). */ \ + CBC_OPCODE (CBC_EXT_END, CBC_NO_FLAG, 0, VM_OC_NONE) + +#define CBC_MAXIMUM_BYTE_VALUE 255 +#define CBC_MAXIMUM_SMALL_VALUE 510 +#define CBC_MAXIMUM_FULL_VALUE 32767 + +#define CBC_PUSH_NUMBER_BYTE_RANGE_END 256 + +#define CBC_HIGHEST_BIT_MASK 0x80 +#define CBC_LOWER_SEVEN_BIT_MASK 0x7f + +/** + * Literal encoding limit when full literal encoding mode is enabled + */ +#define CBC_FULL_LITERAL_ENCODING_LIMIT 128 + +/** + * Literal encoding delta when full literal encoding mode is enabled + */ +#define CBC_FULL_LITERAL_ENCODING_DELTA 0x8000 + +/** + * Literal encoding limit when full literal encoding mode is disabled + */ +#define CBC_SMALL_LITERAL_ENCODING_LIMIT 255 + +/** + * Literal encoding delta when full literal encoding mode is disabled + */ +#define CBC_SMALL_LITERAL_ENCODING_DELTA 0xfe01 + +/** + * Literal indicies belong to one of the following groups: + * + * 0 <= index < argument_end : arguments + * argument_end <= index < register_end : registers + * register_end <= index < ident_end : identifiers + * ident_end <= index < const_literal_end : constant literals + * const_literal_end <= index < literal_end : template literals + */ + +/** + * Compiled byte code arguments. + */ +typedef struct +{ + ecma_compiled_code_t header; /**< compiled code header */ + uint8_t stack_limit; /**< maximum number of values stored on the stack */ + uint8_t argument_end; /**< number of arguments expected by the function */ + ecma_value_t script_value; /**< script value */ + uint8_t register_end; /**< end position of the register group */ + uint8_t ident_end; /**< end position of the identifier group */ + uint8_t const_literal_end; /**< end position of the const literal group */ + uint8_t literal_end; /**< end position of the literal group */ +} cbc_uint8_arguments_t; + +/** + * Compiled byte code arguments. + */ +typedef struct +{ + ecma_compiled_code_t header; /**< compiled code header */ + uint16_t stack_limit; /**< maximum number of values stored on the stack */ + ecma_value_t script_value; /**< script value */ + uint16_t argument_end; /**< number of arguments expected by the function */ + uint16_t register_end; /**< end position of the register group */ + uint16_t ident_end; /**< end position of the identifier group */ + uint16_t const_literal_end; /**< end position of the const literal group */ + uint16_t literal_end; /**< end position of the literal group */ + uint16_t padding; /**< an unused value */ +} cbc_uint16_arguments_t; + +/** + * Compact byte code status flags. + */ +typedef enum +{ + CBC_CODE_FLAGS_FULL_LITERAL_ENCODING = (1u << 0), /**< full literal encoding mode is enabled */ + CBC_CODE_FLAGS_UINT16_ARGUMENTS = (1u << 1), /**< compiled code data is cbc_uint16_arguments_t */ + CBC_CODE_FLAGS_STRICT_MODE = (1u << 2), /**< strict mode is enabled */ + CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED = (1u << 3), /**< mapped arguments object must be constructed */ + CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 4), /**< no need to create a lexical environment */ + CBC_CODE_FLAGS_HAS_EXTENDED_INFO = (1u << 5), /**< this function has extended info block */ + CBC_CODE_FLAGS_HAS_TAGGED_LITERALS = (1u << 6), /**< this function has tagged template literal list */ + CBC_CODE_FLAGS_HAS_LINE_INFO = (1u << 7), /**< this function has line info block */ + CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 8), /**< this function is a static snapshot function */ + CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 9), /**< this function should be ignored by debugger */ + CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED = (1u << 10), /**< compiled code needs a lexical block */ + + /* Bits from bit 12 is reserved for function types (see CBC_FUNCTION_TYPE_SHIFT). + * Note: the last bits are used for type flags because < and >= operators can be used to + check a range of types without decoding the actual type. */ +} cbc_code_flags_t; + +/** + * Optional byte code fields. These fields are stored in a reversed + * order from the end of the byte code data. + * + * Value fields: + * - when CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED is set: + * argument_end number of argument names encoded as strings + * - when function type is not CBC_FUNCTION_CONSTRUCTOR: + * function name encoded as string + * - when CBC_CODE_FLAGS_HAS_TAGGED_LITERALS is set: + * pointer to the tagged template collection encoded as value + * + * Byte fields when CBC_CODE_FLAGS_HAS_EXTENDED_INFO is set: + * - always available: + * a byte which contains a combination of CBC_EXTENDED_CODE_FLAGS bits + * - when CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH is set: + * a vlq encoded default value for function length + * - when CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE is set: + * a pair of vlq encoded values, representing the start and size of the range + */ + +/** + * Compact byte code function types. + */ +typedef enum +{ + /* The first type must be regular expression (see CBC_IS_FUNCTION) */ + CBC_REGULAR_EXPRESSION, /**< regular expression literal */ + CBC_FUNCTION_NORMAL, /**< function without special properties */ + CBC_FUNCTION_CONSTRUCTOR, /**< constructor function */ + + /* The following functions cannot be constructed (see CBC_FUNCTION_IS_CONSTRUCTABLE) */ + CBC_FUNCTION_SCRIPT, /**< script (global) function */ + CBC_FUNCTION_GENERATOR, /**< generator function */ + CBC_FUNCTION_ASYNC_GENERATOR, /**< async generator function */ + + /* The following functions has no prototype (see CBC_FUNCTION_HAS_PROTOTYPE) */ + CBC_FUNCTION_ACCESSOR, /**< property accessor function */ + CBC_FUNCTION_ASYNC, /**< async function */ + CBC_FUNCTION_METHOD, /**< method */ + + /* The following functions are arrow function (see CBC_FUNCTION_IS_ARROW) */ + CBC_FUNCTION_ARROW, /**< arrow function */ + CBC_FUNCTION_ASYNC_ARROW, /**< arrow function */ +} cbc_code_function_types_t; + +/** + * Shift for getting / setting the function type of a byte code. + */ +#define CBC_FUNCTION_TYPE_SHIFT 12 + +/** + * Compute function type bits in code flags. + */ +#define CBC_FUNCTION_TO_TYPE_BITS(name) ((name) << CBC_FUNCTION_TYPE_SHIFT) + +/** + * Get function type from code flags. + */ +#define CBC_FUNCTION_GET_TYPE(flags) ((uint16_t) ((flags) >> CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the byte code is a function or a regular expression. + */ +#define CBC_IS_FUNCTION(flags) ((flags) >= (CBC_FUNCTION_NORMAL << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the function can be constructed with new operator. + */ +#define CBC_FUNCTION_IS_CONSTRUCTABLE(flags) ((flags) < (CBC_FUNCTION_GENERATOR << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the function has prototype property. + */ +#define CBC_FUNCTION_HAS_PROTOTYPE(flags) ((flags) < (CBC_FUNCTION_ACCESSOR << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Checks whether the function is an arrow function. + */ +#define CBC_FUNCTION_IS_ARROW(flags) ((flags) >= (CBC_FUNCTION_ARROW << CBC_FUNCTION_TYPE_SHIFT)) + +/** + * Compact byte code extended status flags. + */ +typedef enum +{ + CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH = (1u << 0), /**< has argument length */ + CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE = (1u << 1), /**< has source code range (start, end) */ + CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS = (1u << 2), /**< source code range is inside + * the function arguments */ +} cbc_extended_code_flags_t; + +/** + * Shared script data. + */ +typedef enum +{ + CBC_SCRIPT_HAS_USER_VALUE = (1 << 0), /**< script has user value */ + CBC_SCRIPT_USER_VALUE_IS_OBJECT = (1 << 1), /**< user value is object */ + CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS = (1 << 2), /**< script is a function with arguments source code */ + CBC_SCRIPT_HAS_IMPORT_META = (1 << 3), /**< script is a module with import.meta object */ + CBC_SCRIPT_IS_EVAL_CODE = (1 << 4), /**< script is compiled by eval like (eval, new Function, etc.) expression */ +} cbc_script_type; + +/** + * Value for increasing or decreasing the script reference counter. + */ +#define CBC_SCRIPT_REF_ONE 0x20 + +/** + * Maximum value of script reference counter. + */ +#define CBC_SCRIPT_REF_MAX (UINT32_MAX - CBC_SCRIPT_REF_ONE + 1) + +/** + * Sets the type of a script using the user_value. + */ +#define CBC_SCRIPT_SET_TYPE(script_p, user_value, ref_count) \ + do \ + { \ + (script_p)->refs_and_type = (ref_count); \ + if ((user_value) != ECMA_VALUE_EMPTY) \ + { \ + (script_p)->refs_and_type |= CBC_SCRIPT_HAS_USER_VALUE; \ + if (ecma_is_value_object (user_value)) \ + { \ + (script_p)->refs_and_type |= CBC_SCRIPT_USER_VALUE_IS_OBJECT; \ + } \ + } \ + } while (false) + +/** + * Shared script data. + */ +typedef struct +{ +#if JERRY_BUILTIN_REALMS + ecma_object_t *realm_p; /**< realm object */ +#endif /* JERRY_BUILTIN_REALMS */ + uint32_t refs_and_type; /**< reference counter and type of the function */ +#if JERRY_SOURCE_NAME + ecma_value_t source_name; /**< source name */ +#endif /* JERRY_SOURCE_NAME */ +#if JERRY_FUNCTION_TO_STRING + ecma_value_t source_code; /**< source code */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} cbc_script_t; + +/** + * Get the array of optional values assigned to a script. + * + * First value: user value + * Second value: function arguments value + */ +#define CBC_SCRIPT_GET_OPTIONAL_VALUES(script_p) ((ecma_value_t *) ((script_p) + 1)) + +/** + * Get user value. + */ +#define CBC_SCRIPT_GET_USER_VALUE(script_p) (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[0]) + +/** + * Get function arguments. + */ +#define CBC_SCRIPT_GET_FUNCTION_ARGUMENTS(script_p, type) \ + (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) &CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0]) + +/** + * Get import.meta object. + */ +#define CBC_SCRIPT_GET_IMPORT_META(script_p, type) \ + (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) &CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0]) + +#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1, + +/** + * Opcode list. + */ +typedef enum +{ + CBC_OPCODE_LIST /**< list of opcodes */ +} cbc_opcode_t; + +/** + * Extended opcode list. + */ +typedef enum +{ + CBC_EXT_OPCODE_LIST /**< list extended opcodes */ +} cbc_ext_opcode_t; + +#undef CBC_OPCODE + +/** + * Opcode flags. + */ +extern const uint8_t cbc_flags[]; +extern const uint8_t cbc_ext_flags[]; + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Opcode names for debugging. + */ +extern const char *const cbc_names[]; +extern const char *const cbc_ext_names[]; + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* !BYTE_CODE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.cpp new file mode 100644 index 00000000..eafd1677 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.cpp @@ -0,0 +1,550 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include "ecma-big-uint.h" +#include "ecma-bigint.h" +#include "ecma-extended-info.h" +#include "ecma-helpers.h" + +#include "js-parser-internal.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +#if JERRY_PARSER + +/** + * Free literal. + */ +void +util_free_literal (lexer_literal_t *literal_p) /**< literal */ +{ + if (literal_p->type == LEXER_IDENT_LITERAL || literal_p->type == LEXER_STRING_LITERAL) + { + if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) + { + jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length); + } + } + else if ((literal_p->type == LEXER_FUNCTION_LITERAL) || (literal_p->type == LEXER_REGEXP_LITERAL)) + { + ecma_bytecode_deref (literal_p->u.bytecode_p); + } +} /* util_free_literal */ + +#endif /* JERRY_PARSER */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Debug utility to print a character sequence. + */ +static void +util_print_chars (const uint8_t *char_p, /**< character pointer */ + size_t size) /**< size */ +{ + while (size > 0) + { + JERRY_DEBUG_MSG ("%c", *char_p++); + size--; + } +} /* util_print_chars */ + +/** + * Debug utility to print a number. + */ +static void +util_print_number (ecma_number_t num_p) /**< number to print */ +{ + lit_utf8_byte_t str_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + lit_utf8_size_t str_size = ecma_number_to_utf8_string (num_p, str_buf, sizeof (str_buf)); + str_buf[str_size] = 0; + JERRY_DEBUG_MSG ("%s", str_buf); +} /* util_print_number */ + +#if JERRY_BUILTIN_BIGINT + +/** + * Debug utility to print a bigint. + */ +static void +util_print_bigint (ecma_value_t bigint) /**< bigint to print */ +{ + if (bigint == ECMA_BIGINT_ZERO) + { + JERRY_DEBUG_MSG ("0"); + return; + } + + ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (bigint); + uint32_t char_start_p, char_size_p; + lit_utf8_byte_t *string_buffer_p = ecma_big_uint_to_string (bigint_p, 10, &char_start_p, &char_size_p); + + if (JERRY_UNLIKELY (string_buffer_p == NULL)) + { + JERRY_DEBUG_MSG (""); + return; + } + + JERRY_ASSERT (char_start_p > 0); + + if (bigint_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + string_buffer_p[--char_start_p] = LIT_CHAR_MINUS; + } + + util_print_chars (string_buffer_p + char_start_p, char_size_p - char_start_p); + jmem_heap_free_block (string_buffer_p, char_size_p); +} /* util_print_bigint */ + +#endif /* JERRY_BUILTIN_BIGINT */ + +/** + * Print literal + */ +void +util_print_literal (lexer_literal_t *literal_p) /**< literal */ +{ + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + JERRY_DEBUG_MSG ("ident("); + util_print_chars (literal_p->u.char_p, literal_p->prop.length); + break; + } + case LEXER_FUNCTION_LITERAL: + { + JERRY_DEBUG_MSG ("function"); + return; + } + case LEXER_STRING_LITERAL: + { + JERRY_DEBUG_MSG ("string("); + util_print_chars (literal_p->u.char_p, literal_p->prop.length); + break; + } + case LEXER_NUMBER_LITERAL: + { +#if JERRY_BUILTIN_BIGINT + if (ecma_is_value_bigint (literal_p->u.value)) + { + JERRY_DEBUG_MSG ("bigint("); + util_print_bigint (literal_p->u.value); + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + JERRY_DEBUG_MSG ("number("); + util_print_number (ecma_get_number_from_value (literal_p->u.value)); + break; + } + case LEXER_REGEXP_LITERAL: + { + JERRY_DEBUG_MSG ("regexp"); + return; + } + default: + { + JERRY_DEBUG_MSG ("unknown"); + return; + } + } + + JERRY_DEBUG_MSG (")"); +} /* util_print_literal */ + +/** + * Print literal. + */ +static void +util_print_literal_value (ecma_compiled_code_t *compiled_code_p, /**< compiled code */ + uint16_t literal_index) /**< literal index */ +{ + uint16_t argument_end; + uint16_t register_end; + uint16_t ident_end; + uint16_t const_literal_end; + ecma_value_t *literal_start_p; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + argument_end = args_p->argument_end; + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + literal_start_p = (ecma_value_t *) (args_p + 1); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + argument_end = args_p->argument_end; + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + literal_start_p = (ecma_value_t *) (args_p + 1); + } + + if (literal_index < argument_end) + { + JERRY_DEBUG_MSG (" arg:%d", literal_index); + return; + } + + if (literal_index < register_end) + { + JERRY_DEBUG_MSG (" reg:%d", literal_index); + return; + } + + if (literal_index >= const_literal_end) + { + JERRY_DEBUG_MSG (" lit:%d", literal_index); + return; + } + + if (literal_index < ident_end) + { + JERRY_DEBUG_MSG (" ident:%d->", literal_index); + } + else + { + JERRY_DEBUG_MSG (" const:%d->", literal_index); + } + + ecma_value_t value = literal_start_p[literal_index - register_end]; + + if (ecma_is_value_number (value)) + { + JERRY_DEBUG_MSG ("number("); + util_print_number (ecma_get_number_from_value (value)); + } +#if JERRY_BUILTIN_BIGINT + else if (ecma_is_value_bigint (value)) + { + JERRY_DEBUG_MSG ("bigint("); + util_print_bigint (value); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_string_t *literal_p = ecma_get_string_from_value (value); + + JERRY_DEBUG_MSG ("string("); + + ECMA_STRING_TO_UTF8_STRING (literal_p, chars_p, literal_size); + util_print_chars (chars_p, literal_size); + ECMA_FINALIZE_UTF8_STRING (chars_p, literal_size); + } + + JERRY_DEBUG_MSG (")"); +} /* util_print_literal_value */ + +#define PARSER_READ_IDENTIFIER_INDEX(name) \ + name = *byte_code_p++; \ + if (name >= encoding_limit) \ + { \ + name = (uint16_t) (((name << 8) | byte_code_p[0]) - encoding_delta); \ + byte_code_p++; \ + } + +/** + * Print byte code. + */ +void +util_print_cbc (ecma_compiled_code_t *compiled_code_p) /**< compiled code */ +{ + uint8_t flags; + uint8_t *byte_code_start_p; + uint8_t *byte_code_end_p; + uint8_t *byte_code_p; + uint16_t encoding_limit; + uint16_t encoding_delta; + uint16_t stack_limit; + uint16_t argument_end; + uint16_t register_end; + uint16_t ident_end; + uint16_t const_literal_end; + uint16_t literal_end; + size_t size = ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args = (cbc_uint16_arguments_t *) compiled_code_p; + stack_limit = args->stack_limit; + argument_end = args->argument_end; + register_end = args->register_end; + ident_end = args->ident_end; + const_literal_end = args->const_literal_end; + literal_end = args->literal_end; + } + else + { + cbc_uint8_arguments_t *args = (cbc_uint8_arguments_t *) compiled_code_p; + stack_limit = args->stack_limit; + argument_end = args->argument_end; + register_end = args->register_end; + ident_end = args->ident_end; + const_literal_end = args->const_literal_end; + literal_end = args->literal_end; + } + + JERRY_DEBUG_MSG ("\nByte code dump:\n\n Maximum stack depth: %d\n Flags: [", (int) (stack_limit + register_end)); + + if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + JERRY_DEBUG_MSG ("small_lit_enc"); + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + JERRY_DEBUG_MSG ("full_lit_enc"); + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + JERRY_DEBUG_MSG (",uint16_arguments"); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) + { + JERRY_DEBUG_MSG (",strict_mode"); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + JERRY_DEBUG_MSG (",mapped_arguments_needed"); + size -= argument_end * sizeof (ecma_value_t); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) + { + JERRY_DEBUG_MSG (",no_lexical_env"); + } + + switch (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags)) + { + case CBC_FUNCTION_CONSTRUCTOR: + { + JERRY_DEBUG_MSG (",constructor"); + break; + } + case CBC_FUNCTION_GENERATOR: + { + JERRY_DEBUG_MSG (",generator"); + break; + } + case CBC_FUNCTION_ASYNC: + { + JERRY_DEBUG_MSG (",async"); + break; + } + case CBC_FUNCTION_ASYNC_GENERATOR: + { + JERRY_DEBUG_MSG (",async_generator"); + break; + } + case CBC_FUNCTION_ACCESSOR: + { + JERRY_DEBUG_MSG (",accessor"); + break; + } + case CBC_FUNCTION_ARROW: + { + JERRY_DEBUG_MSG (",arrow"); + break; + } + case CBC_FUNCTION_ASYNC_ARROW: + { + JERRY_DEBUG_MSG (",async_arrow"); + break; + } + } + + JERRY_DEBUG_MSG ("]\n"); + + JERRY_DEBUG_MSG (" Argument range end: %d\n", (int) argument_end); + JERRY_DEBUG_MSG (" Register range end: %d\n", (int) register_end); + JERRY_DEBUG_MSG (" Identifier range end: %d\n", (int) ident_end); + JERRY_DEBUG_MSG (" Const literal range end: %d\n", (int) const_literal_end); + JERRY_DEBUG_MSG (" Literal range end: %d\n\n", (int) literal_end); + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (compiled_code_p); + uint8_t *extended_info_start_p = extended_info_p + sizeof (uint8_t); + uint8_t extended_info = *extended_info_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + uint32_t argument_length = ecma_extended_info_decode_vlq (&extended_info_p); + JERRY_DEBUG_MSG (" [Extended] Argument length: %d\n", (int) argument_length); + } + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE) + { + uint32_t range_start = ecma_extended_info_decode_vlq (&extended_info_p); + uint32_t range_end = ecma_extended_info_decode_vlq (&extended_info_p) + range_start; + JERRY_DEBUG_MSG (" [Extended] Source code range: %d - %d\n", (int) range_start, (int) range_end); + } + + JERRY_DEBUG_MSG ("\n"); + + size -= (size_t) (extended_info_start_p - extended_info_p); + } + + byte_code_start_p = (uint8_t *) compiled_code_p; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + byte_code_start_p += sizeof (cbc_uint16_arguments_t); + } + else + { + byte_code_start_p += sizeof (cbc_uint8_arguments_t); + } + + byte_code_start_p += (unsigned int) (literal_end - register_end) * sizeof (ecma_value_t); + + if (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR) + { + size -= sizeof (ecma_value_t); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) + { + size -= sizeof (ecma_value_t); + } + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + size -= sizeof (ecma_value_t); + } + + byte_code_end_p = ((uint8_t *) compiled_code_p) + size; + byte_code_p = byte_code_start_p; + + while (byte_code_p < byte_code_end_p) + { + cbc_opcode_t opcode = (cbc_opcode_t) *byte_code_p; + cbc_ext_opcode_t ext_opcode = CBC_EXT_NOP; + size_t cbc_offset = (size_t) (byte_code_p - byte_code_start_p); + + if (opcode != CBC_EXT_OPCODE) + { + flags = cbc_flags[opcode]; + JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_names[opcode]); + byte_code_p++; + } + else + { + if (byte_code_p + 1 >= byte_code_end_p) + { + break; + } + + ext_opcode = (cbc_ext_opcode_t) byte_code_p[1]; + + if (ext_opcode == CBC_EXT_NOP) + { + break; + } + + flags = cbc_ext_flags[ext_opcode]; + JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_ext_names[ext_opcode]); + byte_code_p += 2; + } + + if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint16_t literal_index; + + PARSER_READ_IDENTIFIER_INDEX (literal_index); + util_print_literal_value (compiled_code_p, literal_index); + } + + if (flags & CBC_HAS_LITERAL_ARG2) + { + uint16_t literal_index; + + PARSER_READ_IDENTIFIER_INDEX (literal_index); + util_print_literal_value (compiled_code_p, literal_index); + + if (!(flags & CBC_HAS_LITERAL_ARG)) + { + PARSER_READ_IDENTIFIER_INDEX (literal_index); + util_print_literal_value (compiled_code_p, literal_index); + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + if (opcode == CBC_PUSH_NUMBER_POS_BYTE || opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", (int) *byte_code_p + 1); + } + else if (opcode == CBC_PUSH_NUMBER_NEG_BYTE || opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", -((int) *byte_code_p + 1)); + } + else + { + JERRY_DEBUG_MSG (" byte_arg:%d", *byte_code_p); + } + byte_code_p++; + } + + if (flags & CBC_HAS_BRANCH_ARG) + { + size_t branch_offset_length = + (opcode != CBC_EXT_OPCODE ? CBC_BRANCH_OFFSET_LENGTH (opcode) : CBC_BRANCH_OFFSET_LENGTH (ext_opcode)); + size_t offset = 0; + + do + { + offset = (offset << 8) | *byte_code_p++; + } while (--branch_offset_length > 0); + + JERRY_DEBUG_MSG (" offset:%d(->%d)", + (int) offset, + (int) (cbc_offset + (CBC_BRANCH_IS_FORWARD (flags) ? offset : -offset))); + } + + JERRY_DEBUG_MSG ("\n"); + } +} /* util_print_cbc */ + +#undef PARSER_READ_IDENTIFIER_INDEX + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.h new file mode 100644 index 00000000..3ebdbbe4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/common.h @@ -0,0 +1,162 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +#include "ecma-globals.h" +#include "ecma-regexp-object.h" + +#include "jerry-config.h" +#include "jmem.h" + +/* Immediate management. */ + +/** + * Literal types. + * + * The LEXER_UNUSED_LITERAL type is internal and + * used for various purposes. + */ +typedef enum +{ + /* The LEXER_IS_IDENT_OR_STRING macro must be updated if the order is changed. */ + LEXER_IDENT_LITERAL = 0, /**< identifier literal */ + LEXER_STRING_LITERAL = 1, /**< string literal */ + LEXER_NUMBER_LITERAL = 2, /**< number literal */ + LEXER_FUNCTION_LITERAL = 3, /**< function literal */ + LEXER_REGEXP_LITERAL = 4, /**< regexp literal */ + LEXER_UNUSED_LITERAL = 5, /**< unused literal, can only be + used by the byte code generator. */ + LEXER_NEW_IDENT_LITERAL = 6, /**< new local variable, can only be + used by the byte code generator. */ +} lexer_literal_type_t; + +/** + * Checks whether the literal type is identifier or string. + */ +#define LEXER_IS_IDENT_OR_STRING(literal_type) ((literal_type) <= LEXER_STRING_LITERAL) + +/** + * Flag bits for status_flags member of lexer_literal_t. + */ +typedef enum +{ + LEXER_FLAG_USED = (1 << 0), /**< this local identifier needs to be stored in the constant pool */ + LEXER_FLAG_FUNCTION_ARGUMENT = (1 << 1), /**< this local identifier is a function argument */ + LEXER_FLAG_SOURCE_PTR = (1 << 2), /**< the literal is directly referenced in the source code + * (no need to allocate memory) */ + LEXER_FLAG_LATE_INIT = (1 << 3), /**< initialize this variable after the byte code is freed */ + LEXER_FLAG_ASCII = (1 << 4), /**< the literal contains only ascii characters */ + LEXER_FLAG_GLOBAL = (1 << 5), /**< this local identifier is not a let or const declaration */ +} lexer_literal_status_flags_t; + +/** + * Type of property length. + */ +#if JERRY_CPOINTER_32_BIT +typedef uint32_t prop_length_t; +#else /* !JERRY_CPOINTER_32_BIT */ +typedef uint16_t prop_length_t; +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Literal data. + */ +typedef struct +{ + union + { + ecma_value_t value; /**< literal value (not processed by the parser) */ + const uint8_t *char_p; /**< character value */ + ecma_compiled_code_t *bytecode_p; /**< compiled function or regexp pointer */ + uint32_t source_data; /**< encoded source literal */ + } u; + +#if JERRY_PARSER_DUMP_BYTE_CODE + struct +#else /* !JERRY_PARSER_DUMP_BYTE_CODE */ + union +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + { + prop_length_t length; /**< length of ident / string literal */ + uint16_t index; /**< real index during post processing */ + } prop; + + uint8_t type; /**< type of the literal */ + uint8_t status_flags; /**< status flags */ +} lexer_literal_t; + +void util_free_literal (lexer_literal_t *literal_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE +void util_print_literal (lexer_literal_t *); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * Source code line counter type. + */ +typedef uint32_t parser_line_counter_t; + +/** + * Source code as character data. + */ +typedef struct +{ + const uint8_t *source_p; /**< valid UTF-8 source code */ + size_t source_size; /**< size of the source code */ +} parser_source_char_t; + +/* TRY/CATCH block */ + +#define PARSER_TRY_CONTEXT(context_name) jmp_buf context_name + +#define PARSER_THROW(context_name) longjmp (context_name, 1); + +#define PARSER_TRY(context_name) \ + { \ + if (!setjmp (context_name)) \ + { +#define PARSER_CATCH \ + } \ + else \ + { +#define PARSER_TRY_END \ + } \ + } + +/** + * @} + * @} + * @} + */ + +#endif /* !COMMON_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.cpp new file mode 100644 index 00000000..c6c2db64 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.cpp @@ -0,0 +1,3622 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-function-object.h" +#include "ecma-helpers.h" +#include "ecma-literal-storage.h" + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_lexer Lexer + * @{ + */ + +JERRY_STATIC_ASSERT (((int)LEXER_NUMBER_BINARY > (int)LEXER_NUMBER_OCTAL), + lexer_number_binary_must_be_greater_than_lexer_number_octal); + +/** + * Check whether the UTF-8 intermediate is an octet or not + */ +#define IS_UTF8_INTERMEDIATE_OCTET(byte) (((byte) &LIT_UTF8_EXTRA_BYTE_MASK) == LIT_UTF8_2_BYTE_CODE_POINT_MIN) + +/** + * Align column to the next tab position. + * + * @return aligned position + */ +static parser_line_counter_t +align_column_to_tab (parser_line_counter_t column) /**< current column */ +{ + /* Tab aligns to zero column start position. */ + return (parser_line_counter_t) (((column + (8u - 1u)) & ~ECMA_STRING_CONTAINER_MASK) + 1u); +} /* align_column_to_tab */ + +/** + * Parse hexadecimal character sequence + * + * @return character value or UINT32_MAX on error + */ +static lit_code_point_t +lexer_hex_to_code_point (const uint8_t *source_p, /**< current source position */ + parser_line_counter_t length) /**< source length */ +{ + lit_code_point_t result = 0; + + do + { + uint32_t byte = *source_p++; + + result <<= 4; + + if (byte >= LIT_CHAR_0 && byte <= LIT_CHAR_9) + { + result += byte - LIT_CHAR_0; + } + else + { + byte = LEXER_TO_ASCII_LOWERCASE (byte); + if (byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F) + { + result += byte - (LIT_CHAR_LOWERCASE_A - 10); + } + else + { + return UINT32_MAX; + } + } + } while (--length > 0); + + return result; +} /* lexer_hex_to_code_point */ + +/** + * Parse hexadecimal character sequence enclosed in braces + * + * @return character value or UINT32_MAX on error + */ +static lit_code_point_t +lexer_hex_in_braces_to_code_point (const uint8_t *source_p, /**< current source position */ + const uint8_t *source_end_p, /**< source end */ + uint32_t *length_p) /**< [out] length of the sequence */ +{ + lit_code_point_t result = 0; + /* Four is the size of \u{} sequence. */ + uint32_t length = 4; + + JERRY_ASSERT (source_p[-1] == LIT_CHAR_LEFT_BRACE); + JERRY_ASSERT (source_p < source_end_p); + + do + { + uint32_t byte = *source_p++; + + result <<= 4; + + if (byte >= LIT_CHAR_0 && byte <= LIT_CHAR_9) + { + result += byte - LIT_CHAR_0; + } + else + { + byte = LEXER_TO_ASCII_LOWERCASE (byte); + if (byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F) + { + result += byte - (LIT_CHAR_LOWERCASE_A - 10); + } + else + { + return UINT32_MAX; + } + } + + if (result >= (LIT_UNICODE_CODE_POINT_MAX + 1) || source_p >= source_end_p) + { + return UINT32_MAX; + } + length++; + } while (*source_p != LIT_CHAR_RIGHT_BRACE); + + *length_p = length; + return result; +} /* lexer_hex_in_braces_to_code_point */ + +/** + * Parse hexadecimal character sequence + * + * @return character value + */ +static lit_code_point_t +lexer_unchecked_hex_to_character (const uint8_t **source_p) /**< [in, out] current source position */ +{ + lit_code_point_t result = 0; + const uint8_t *char_p = *source_p; + uint32_t length = (char_p[-1] == LIT_CHAR_LOWERCASE_U) ? 4 : 2; + + if (char_p[0] == LIT_CHAR_LEFT_BRACE) + { + length = 0; + char_p++; + } + + while (true) + { + uint32_t byte = *char_p++; + + result <<= 4; + + if (byte >= LIT_CHAR_0 && byte <= LIT_CHAR_9) + { + result += byte - LIT_CHAR_0; + } + else + { + JERRY_ASSERT ((byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F) + || (byte >= LIT_CHAR_UPPERCASE_A && byte <= LIT_CHAR_UPPERCASE_F)); + + result += LEXER_TO_ASCII_LOWERCASE (byte) - (LIT_CHAR_LOWERCASE_A - 10); + } + + JERRY_ASSERT (result <= LIT_UNICODE_CODE_POINT_MAX); + + if (length == 0) + { + if (*char_p != LIT_CHAR_RIGHT_BRACE) + { + continue; + } + + *source_p = char_p + 1; + return result; + } + + if (--length == 0) + { + *source_p = char_p; + return result; + } + } +} /* lexer_unchecked_hex_to_character */ + +/** + * Skip space mode + */ +typedef enum +{ + LEXER_SKIP_SPACES, /**< skip spaces mode */ + LEXER_SKIP_SINGLE_LINE_COMMENT, /**< parse single line comment */ + LEXER_SKIP_MULTI_LINE_COMMENT, /**< parse multi line comment */ +} skip_mode_t; + +/** + * Skip spaces. + */ +static void +lexer_skip_spaces (parser_context_t *context_p) /**< context */ +{ + skip_mode_t mode = LEXER_SKIP_SPACES; + const uint8_t *source_end_p = context_p->source_end_p; + + if (context_p->token.flags & LEXER_NO_SKIP_SPACES) + { + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + return; + } + + context_p->token.flags = 0; + + while (true) + { + if (context_p->source_p >= source_end_p) + { + if (mode == LEXER_SKIP_MULTI_LINE_COMMENT) + { + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_MULTILINE_COMMENT); + } + return; + } + + switch (context_p->source_p[0]) + { + case LIT_CHAR_CR: + { + if (context_p->source_p + 1 < source_end_p && context_p->source_p[1] == LIT_CHAR_LF) + { + context_p->source_p++; + } + /* FALLTHRU */ + } + + case LIT_CHAR_LF: + { + context_p->line++; + context_p->column = 0; + context_p->token.flags = LEXER_WAS_NEWLINE; + + if (mode == LEXER_SKIP_SINGLE_LINE_COMMENT) + { + mode = LEXER_SKIP_SPACES; + } + /* FALLTHRU */ + } + + case LIT_CHAR_VTAB: + case LIT_CHAR_FF: + case LIT_CHAR_SP: + { + context_p->source_p++; + context_p->column++; + continue; + } + + case LIT_CHAR_TAB: + { + context_p->column = align_column_to_tab (context_p->column); + context_p->source_p++; + continue; + } + + case LIT_CHAR_SLASH: + { + if (mode == LEXER_SKIP_SPACES && context_p->source_p + 1 < source_end_p) + { + if (context_p->source_p[1] == LIT_CHAR_SLASH) + { + mode = LEXER_SKIP_SINGLE_LINE_COMMENT; + } + else if (context_p->source_p[1] == LIT_CHAR_ASTERISK) + { + mode = LEXER_SKIP_MULTI_LINE_COMMENT; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + } + + if (mode != LEXER_SKIP_SPACES) + { + context_p->source_p += 2; + PARSER_PLUS_EQUAL_LC (context_p->column, 2); + continue; + } + } + break; + } + + case LIT_CHAR_ASTERISK: + { + if (mode == LEXER_SKIP_MULTI_LINE_COMMENT && context_p->source_p + 1 < source_end_p + && context_p->source_p[1] == LIT_CHAR_SLASH) + { + mode = LEXER_SKIP_SPACES; + context_p->source_p += 2; + PARSER_PLUS_EQUAL_LC (context_p->column, 2); + continue; + } + break; + } + + case 0xc2: + { + if (context_p->source_p + 1 < source_end_p && context_p->source_p[1] == 0xa0) + { + /* Codepoint \u00A0 */ + context_p->source_p += 2; + context_p->column++; + continue; + } + break; + } + + case LEXER_NEWLINE_LS_PS_BYTE_1: + { + JERRY_ASSERT (context_p->source_p + 2 < source_end_p); + if (LEXER_NEWLINE_LS_PS_BYTE_23 (context_p->source_p)) + { + /* Codepoint \u2028 and \u2029 */ + context_p->source_p += 3; + context_p->line++; + context_p->column = 1; + context_p->token.flags = LEXER_WAS_NEWLINE; + + if (mode == LEXER_SKIP_SINGLE_LINE_COMMENT) + { + mode = LEXER_SKIP_SPACES; + } + continue; + } + break; + } + + case 0xef: + { + if (context_p->source_p + 2 < source_end_p && context_p->source_p[1] == 0xbb && context_p->source_p[2] == 0xbf) + { + /* Codepoint \uFEFF */ + context_p->source_p += 3; + context_p->column++; + continue; + } + break; + } + + default: + { + break; + } + } + + if (mode == LEXER_SKIP_SPACES) + { + return; + } + + context_p->source_p++; + + if (context_p->source_p < source_end_p && !IS_UTF8_INTERMEDIATE_OCTET (context_p->source_p[0])) + { + context_p->column++; + } + } +} /* lexer_skip_spaces */ + +/** + * Skip all the continuous empty statements. + */ +void +lexer_skip_empty_statements (parser_context_t *context_p) /**< context */ +{ + lexer_skip_spaces (context_p); + + while (context_p->source_p < context_p->source_end_p && *context_p->source_p == LIT_CHAR_SEMICOLON) + { + lexer_consume_next_character (context_p); + lexer_skip_spaces (context_p); + } + + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); +} /* lexer_skip_empty_statements */ + +/** + * Checks whether the keyword has escape sequences. + */ +#define LEXER_CHECK_INVALID_KEYWORD(ident_start_p, buffer_p) \ + (JERRY_UNLIKELY ((ident_start_p) == (buffer_p)) \ + && !(context_p->global_status_flags & ECMA_PARSE_INTERNAL_PRE_SCANNING)) + +/** + * Keyword data. + */ +typedef struct +{ + const uint8_t *keyword_p; /**< keyword string */ + lexer_token_type_t type; /**< keyword token type */ +} keyword_string_t; + +/** + * @{ + * Keyword defines + */ +#define LEXER_KEYWORD(name, type) \ + { \ + (const uint8_t *) (name), (type) \ + } +#define LEXER_KEYWORD_LIST_LENGTH(name) (const uint8_t) (sizeof ((name)) / sizeof ((name)[0])) +/** @} */ + +/** + * Length of the shortest keyword. + */ +#define LEXER_KEYWORD_MIN_LENGTH 2 + +/** + * Length of the longest keyword. + */ +#define LEXER_KEYWORD_MAX_LENGTH 10 + +/** + * Keywords with 2 characters. + */ +static const keyword_string_t keywords_with_length_2[] = { + LEXER_KEYWORD ("do", LEXER_KEYW_DO), + LEXER_KEYWORD ("if", LEXER_KEYW_IF), + LEXER_KEYWORD ("in", LEXER_KEYW_IN), +}; + +/** + * Keywords with 3 characters. + */ +static const keyword_string_t keywords_with_length_3[] = { + LEXER_KEYWORD ("for", LEXER_KEYW_FOR), LEXER_KEYWORD ("let", LEXER_KEYW_LET), LEXER_KEYWORD ("new", LEXER_KEYW_NEW), + LEXER_KEYWORD ("try", LEXER_KEYW_TRY), LEXER_KEYWORD ("var", LEXER_KEYW_VAR), +}; + +/** + * Keywords with 4 characters. + */ +static const keyword_string_t keywords_with_length_4[] = { + LEXER_KEYWORD ("case", LEXER_KEYW_CASE), LEXER_KEYWORD ("else", LEXER_KEYW_ELSE), + LEXER_KEYWORD ("enum", LEXER_KEYW_ENUM), LEXER_KEYWORD ("eval", LEXER_KEYW_EVAL), +#if JERRY_MODULE_SYSTEM + LEXER_KEYWORD ("meta", LEXER_KEYW_META), +#endif /* JERRY_MODULE_SYSTEM */ + LEXER_KEYWORD ("null", LEXER_LIT_NULL), LEXER_KEYWORD ("this", LEXER_KEYW_THIS), + LEXER_KEYWORD ("true", LEXER_LIT_TRUE), LEXER_KEYWORD ("void", LEXER_KEYW_VOID), + LEXER_KEYWORD ("with", LEXER_KEYW_WITH), +}; + +/** + * Keywords with 5 characters. + */ +static const keyword_string_t keywords_with_length_5[] = { + LEXER_KEYWORD ("async", LEXER_KEYW_ASYNC), LEXER_KEYWORD ("await", LEXER_KEYW_AWAIT), + LEXER_KEYWORD ("break", LEXER_KEYW_BREAK), LEXER_KEYWORD ("catch", LEXER_KEYW_CATCH), + LEXER_KEYWORD ("class", LEXER_KEYW_CLASS), LEXER_KEYWORD ("const", LEXER_KEYW_CONST), + LEXER_KEYWORD ("false", LEXER_LIT_FALSE), LEXER_KEYWORD ("super", LEXER_KEYW_SUPER), + LEXER_KEYWORD ("throw", LEXER_KEYW_THROW), LEXER_KEYWORD ("while", LEXER_KEYW_WHILE), + LEXER_KEYWORD ("yield", LEXER_KEYW_YIELD), +}; + +/** + * Keywords with 6 characters. + */ +static const keyword_string_t keywords_with_length_6[] = { + LEXER_KEYWORD ("delete", LEXER_KEYW_DELETE), LEXER_KEYWORD ("export", LEXER_KEYW_EXPORT), + LEXER_KEYWORD ("import", LEXER_KEYW_IMPORT), LEXER_KEYWORD ("public", LEXER_KEYW_PUBLIC), + LEXER_KEYWORD ("return", LEXER_KEYW_RETURN), LEXER_KEYWORD ("static", LEXER_KEYW_STATIC), + LEXER_KEYWORD ("switch", LEXER_KEYW_SWITCH), LEXER_KEYWORD ("typeof", LEXER_KEYW_TYPEOF), +}; + +/** + * Keywords with 7 characters. + */ +static const keyword_string_t keywords_with_length_7[] = { + LEXER_KEYWORD ("default", LEXER_KEYW_DEFAULT), LEXER_KEYWORD ("extends", LEXER_KEYW_EXTENDS), + LEXER_KEYWORD ("finally", LEXER_KEYW_FINALLY), LEXER_KEYWORD ("package", LEXER_KEYW_PACKAGE), + LEXER_KEYWORD ("private", LEXER_KEYW_PRIVATE), +}; + +/** + * Keywords with 8 characters. + */ +static const keyword_string_t keywords_with_length_8[] = { + LEXER_KEYWORD ("continue", LEXER_KEYW_CONTINUE), + LEXER_KEYWORD ("debugger", LEXER_KEYW_DEBUGGER), + LEXER_KEYWORD ("function", LEXER_KEYW_FUNCTION), +}; + +/** + * Keywords with 9 characters. + */ +static const keyword_string_t keywords_with_length_9[] = { + LEXER_KEYWORD ("arguments", LEXER_KEYW_ARGUMENTS), + LEXER_KEYWORD ("interface", LEXER_KEYW_INTERFACE), + LEXER_KEYWORD ("protected", LEXER_KEYW_PROTECTED), +}; + +/** + * Keywords with 10 characters. + */ +static const keyword_string_t keywords_with_length_10[] = { + LEXER_KEYWORD ("implements", LEXER_KEYW_IMPLEMENTS), + LEXER_KEYWORD ("instanceof", LEXER_KEYW_INSTANCEOF), +}; + +/** + * List of the keyword groups. + */ +static const keyword_string_t *const keyword_strings_list[] = { keywords_with_length_2, keywords_with_length_3, + keywords_with_length_4, keywords_with_length_5, + keywords_with_length_6, keywords_with_length_7, + keywords_with_length_8, keywords_with_length_9, + keywords_with_length_10 }; + +JERRY_STATIC_ASSERT ((sizeof (keyword_strings_list) / sizeof (const keyword_string_t *) == (LEXER_KEYWORD_MAX_LENGTH - LEXER_KEYWORD_MIN_LENGTH) + 1), + keyword_strings_list_size_must_equal_to_keyword_max_length_difference); + +/** + * List of the keyword groups length. + */ +static const uint8_t keyword_lengths_list[] = { + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_2), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_3), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_4), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_5), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_6), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_7), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_8), LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_9), + LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_10) +}; + +#undef LEXER_KEYWORD +#undef LEXER_KEYWORD_LIST_LENGTH + +JERRY_STATIC_ASSERT (((int)LEXER_FIRST_NON_RESERVED_KEYWORD < (int)LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD), + lexer_first_non_reserved_keyword_must_be_before_lexer_first_future_strict_reserved_word); + +/** + * Parse identifier. + * + * @return true, if an identifier is parsed, false otherwise + */ +static bool +lexer_parse_identifier (parser_context_t *context_p, /**< context */ + lexer_parse_options_t options) /**< check keywords */ +{ + /* Only very few identifiers contains \u escape sequences. */ + const uint8_t *source_p = context_p->source_p; + /* Note: newline or tab cannot be part of an identifier. */ + parser_line_counter_t column = context_p->column; + const uint8_t *source_end_p = context_p->source_end_p; + size_t length = 0; + lexer_lit_location_flags_t status_flags = LEXER_LIT_LOCATION_IS_ASCII; + + do + { + if (*source_p == LIT_CHAR_BACKSLASH) + { + /* After a backslash an identifier must start. */ + lit_code_point_t code_point = UINT32_MAX; + uint32_t escape_length = 6; + + if (options & (LEXER_PARSE_CHECK_START_AND_RETURN | LEXER_PARSE_CHECK_PART_AND_RETURN)) + { + return true; + } + + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + + if (source_p + 5 <= source_end_p && source_p[1] == LIT_CHAR_LOWERCASE_U) + { + if (source_p[2] == LIT_CHAR_LEFT_BRACE) + { + code_point = lexer_hex_in_braces_to_code_point (source_p + 3, source_end_p, &escape_length); + } + else if (source_p + 6 <= source_end_p) + { + code_point = lexer_hex_to_code_point (source_p + 2, 4); + } + } + + if (code_point == UINT32_MAX) + { + context_p->source_p = source_p; + context_p->token.column = column; + parser_raise_error (context_p, PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + + if (length == 0) + { + if (!lit_code_point_is_identifier_start (code_point)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_IDENTIFIER_START); + } + } + else + { + if (!lit_code_point_is_identifier_part (code_point)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_IDENTIFIER_PART); + } + } + + length += lit_code_point_get_cesu8_length (code_point); + source_p += escape_length; + PARSER_PLUS_EQUAL_LC (column, escape_length); + continue; + } + + lit_code_point_t code_point = *source_p; + lit_utf8_size_t utf8_length = 1, decoded_length = 1, char_count = 1; + + if (JERRY_UNLIKELY (code_point >= LIT_UTF8_2_BYTE_MARKER)) + { + status_flags = (lexer_lit_location_flags_t) ((uint32_t) status_flags & (uint32_t) ~LEXER_LIT_LOCATION_IS_ASCII); + + utf8_length = lit_read_code_point_from_utf8 (source_p, (lit_utf8_size_t) (source_end_p - source_p), &code_point); + decoded_length = utf8_length; + + /* Only ES2015+ supports code points outside of the basic plane which can be part of an identifier. */ + if ((code_point >= LIT_UTF16_HIGH_SURROGATE_MIN && code_point <= LIT_UTF16_HIGH_SURROGATE_MAX) + && source_p + 3 < source_end_p) + { + lit_code_point_t low_surrogate; + lit_read_code_point_from_utf8 (source_p + 3, (lit_utf8_size_t) (source_end_p - (source_p + 3)), &low_surrogate); + + if (low_surrogate >= LIT_UTF16_LOW_SURROGATE_MIN && low_surrogate <= LIT_UTF16_LOW_SURROGATE_MAX) + { + code_point = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) code_point, (ecma_char_t) low_surrogate); + utf8_length = 2 * 3; + decoded_length = 2 * 3; + char_count = 2; + } + } + else if (source_p[0] >= LIT_UTF8_4_BYTE_MARKER) + { + decoded_length = 2 * 3; + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; +#if JERRY_FUNCTION_TO_STRING + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER; +#endif /* JERRY_FUNCTION_TO_STRING */ + } + } + + if (length == 0) + { + if (JERRY_UNLIKELY (options & (LEXER_PARSE_CHECK_START_AND_RETURN | LEXER_PARSE_CHECK_PART_AND_RETURN))) + { + if (options & LEXER_PARSE_CHECK_START_AND_RETURN) + { + return lit_code_point_is_identifier_start (code_point); + } + else + { + return lit_code_point_is_identifier_part (code_point); + } + } + + if (!lit_code_point_is_identifier_start (code_point)) + { + return false; + } + } + else if (!lit_code_point_is_identifier_part (code_point)) + { + break; + } + + source_p += utf8_length; + length += decoded_length; + PARSER_PLUS_EQUAL_LC (column, char_count); + } while (source_p < source_end_p); + + JERRY_ASSERT (length > 0); + + context_p->token.type = LEXER_LITERAL; + context_p->token.lit_location.type = LEXER_IDENT_LITERAL; + context_p->token.lit_location.status_flags = (uint8_t) status_flags; + + context_p->token.column = context_p->column; + context_p->token.lit_location.char_p = context_p->source_p; + context_p->token.lit_location.length = (prop_length_t) length; + + if (JERRY_UNLIKELY (length > PARSER_MAXIMUM_IDENT_LENGTH)) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_TOO_LONG); + } + + /* Check keywords. */ + if ((options & LEXER_PARSE_CHECK_KEYWORDS) + && (length >= LEXER_KEYWORD_MIN_LENGTH && length <= LEXER_KEYWORD_MAX_LENGTH)) + { + const uint8_t *ident_start_p = context_p->source_p; + uint8_t buffer_p[LEXER_KEYWORD_MAX_LENGTH]; + + if (JERRY_UNLIKELY (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + lexer_convert_ident_to_cesu8 (buffer_p, ident_start_p, (prop_length_t) length); + ident_start_p = buffer_p; + } + + const keyword_string_t *keyword_list_p = keyword_strings_list[length - LEXER_KEYWORD_MIN_LENGTH]; + + int start = 0; + int end = keyword_lengths_list[length - LEXER_KEYWORD_MIN_LENGTH]; + int middle = end / 2; + + do + { + const keyword_string_t *keyword_p = keyword_list_p + middle; + int compare_result = ident_start_p[0] - keyword_p->keyword_p[0]; + + if (compare_result == 0) + { + compare_result = memcmp (ident_start_p, keyword_p->keyword_p, length); + + if (compare_result == 0) + { + context_p->token.keyword_type = (uint8_t) keyword_p->type; + + if (JERRY_LIKELY (keyword_p->type < LEXER_FIRST_NON_RESERVED_KEYWORD)) + { + if (JERRY_UNLIKELY (keyword_p->type == LEXER_KEYW_AWAIT)) + { + if (!(context_p->status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_CLASS_STATIC_BLOCK)) + && !(context_p->global_status_flags & ECMA_PARSE_MODULE)) + { + break; + } + + if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD) + { + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED); + } + + context_p->token.type = (uint8_t) LEXER_KEYW_AWAIT; + break; + } + + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + /* Escape sequences are not allowed in a keyword. */ + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + + context_p->token.type = (uint8_t) keyword_p->type; + break; + } + + if (keyword_p->type == LEXER_KEYW_LET && (context_p->status_flags & PARSER_IS_STRICT)) + { + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + + context_p->token.type = (uint8_t) LEXER_KEYW_LET; + break; + } + + if (keyword_p->type == LEXER_KEYW_YIELD && (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)) + { + if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD) + { + if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + parser_raise_error (context_p, PARSER_ERR_YIELD_NOT_ALLOWED); + } + + context_p->token.type = (uint8_t) LEXER_KEYW_YIELD; + break; + } + + if (keyword_p->type == LEXER_KEYW_ARGUMENTS && (context_p->status_flags & PARSER_INSIDE_CLASS_FIELD)) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_IN_CLASS_FIELD); + } + + if (keyword_p->type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD && (context_p->status_flags & PARSER_IS_STRICT) + && !(options & LEXER_PARSE_NO_STRICT_IDENT_ERROR)) + { + parser_raise_error (context_p, PARSER_ERR_STRICT_IDENT_NOT_ALLOWED); + } + break; + } + } + + if (compare_result > 0) + { + start = middle + 1; + } + else + { + JERRY_ASSERT (compare_result < 0); + end = middle; + } + + middle = (start + end) / 2; + } while (start < end); + } + + context_p->source_p = source_p; + context_p->column = column; + return true; +} /* lexer_parse_identifier */ + +#undef LEXER_CHECK_INVALID_KEYWORD + +/** + * Parse string. + */ +void +lexer_parse_string (parser_context_t *context_p, /**< context */ + lexer_string_options_t opts) /**< options */ +{ + int32_t raw_length_adjust = 0; + + uint8_t str_end_character = context_p->source_p[0]; + const uint8_t *source_p = context_p->source_p + 1; + const uint8_t *string_start_p = source_p; + const uint8_t *source_end_p = context_p->source_end_p; + parser_line_counter_t line = context_p->line; + parser_line_counter_t column = (parser_line_counter_t) (context_p->column + 1); + parser_line_counter_t original_line = line; + parser_line_counter_t original_column = column; + size_t length = 0; + lexer_lit_location_flags_t status_flags = LEXER_LIT_LOCATION_IS_ASCII; + + if (str_end_character == LIT_CHAR_RIGHT_BRACE) + { + str_end_character = LIT_CHAR_GRAVE_ACCENT; + } + + while (true) + { + if (source_p >= source_end_p) + { + context_p->token.line = original_line; + context_p->token.column = (parser_line_counter_t) (original_column - 1); + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_STRING); + } + + if (*source_p == str_end_character) + { + break; + } + + if (*source_p == LIT_CHAR_BACKSLASH) + { + source_p++; + column++; + if (source_p >= source_end_p) + { + /* Will throw an unterminated string error. */ + continue; + } + + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + + /* Newline is ignored. */ + if (*source_p == LIT_CHAR_CR) + { + source_p++; + if (source_p < source_end_p && *source_p == LIT_CHAR_LF) + { + raw_length_adjust--; + source_p++; + } + + line++; + column = 1; + continue; + } + else if (*source_p == LIT_CHAR_LF) + { + source_p++; + line++; + column = 1; + continue; + } + else if (*source_p == LEXER_NEWLINE_LS_PS_BYTE_1 && LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + source_p += 3; + line++; + column = 1; + continue; + } + + if (opts & LEXER_STRING_RAW) + { + if ((*source_p == LIT_CHAR_GRAVE_ACCENT) || (*source_p == LIT_CHAR_BACKSLASH)) + { + source_p++; + column++; + length++; + } + continue; + } + + if (*source_p == LIT_CHAR_0 && source_p + 1 < source_end_p + && (*(source_p + 1) < LIT_CHAR_0 || *(source_p + 1) > LIT_CHAR_9)) + { + source_p++; + column++; + length++; + continue; + } + + /* Except \x, \u, and octal numbers, everything is + * converted to a character which has the same byte length. */ + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_3) + { + if (str_end_character == LIT_CHAR_GRAVE_ACCENT) + { + parser_raise_error (context_p, PARSER_ERR_TEMPLATE_STR_OCTAL_ESCAPE); + } + + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_OCTAL_ESCAPE_NOT_ALLOWED); + } + + source_p++; + column++; + + if (source_p < source_end_p && *source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + source_p++; + column++; + + if (source_p < source_end_p && *source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + /* Numbers >= 0x200 (0x80) requires + * two bytes for encoding in UTF-8. */ + if (source_p[-2] >= LIT_CHAR_2) + { + length++; + } + + source_p++; + column++; + } + } + + length++; + continue; + } + + if (*source_p >= LIT_CHAR_4 && *source_p <= LIT_CHAR_7) + { + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_OCTAL_ESCAPE_NOT_ALLOWED); + } + + source_p++; + column++; + + if (source_p < source_end_p && *source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + source_p++; + column++; + } + + /* The maximum number is 0x4d so the UTF-8 + * representation is always one byte. */ + length++; + continue; + } + + if (*source_p == LIT_CHAR_LOWERCASE_X || *source_p == LIT_CHAR_LOWERCASE_U) + { + uint32_t escape_length = (*source_p == LIT_CHAR_LOWERCASE_X) ? 3 : 5; + lit_code_point_t code_point = UINT32_MAX; + + if (source_p + 4 <= source_end_p && source_p[0] == LIT_CHAR_LOWERCASE_U && source_p[1] == LIT_CHAR_LEFT_BRACE) + { + code_point = lexer_hex_in_braces_to_code_point (source_p + 2, source_end_p, &escape_length); + escape_length--; + } + else + { + if (source_p + escape_length <= source_end_p) + { + code_point = lexer_hex_to_code_point (source_p + 1, escape_length - 1); + } + } + + if (code_point == UINT32_MAX) + { + context_p->token.line = line; + context_p->token.column = (parser_line_counter_t) (column - 1); + parser_raise_error (context_p, PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + + length += lit_code_point_get_cesu8_length (code_point); + + source_p += escape_length; + PARSER_PLUS_EQUAL_LC (column, escape_length); + continue; + } + } + else if (str_end_character == LIT_CHAR_GRAVE_ACCENT && source_p[0] == LIT_CHAR_DOLLAR_SIGN + && source_p + 1 < source_end_p && source_p[1] == LIT_CHAR_LEFT_BRACE) + { + raw_length_adjust--; + source_p++; + break; + } + + if (*source_p >= LIT_UTF8_4_BYTE_MARKER) + { + /* Processing 4 byte unicode sequence (even if it is + * after a backslash). Always converted to two 3 byte + * long sequence. */ + length += 2 * 3; + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + source_p += 4; + raw_length_adjust += 2; + column++; +#if JERRY_FUNCTION_TO_STRING + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER; +#endif /* JERRY_FUNCTION_TO_STRING */ + continue; + } + else if (*source_p == LIT_CHAR_TAB) + { + column = align_column_to_tab (column); + /* Subtract -1 because column is increased below. */ + column--; + } + else if (*source_p == LEXER_NEWLINE_LS_PS_BYTE_1 && LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + source_p += 3; + length += 3; + line++; + column = 1; + continue; + } + else if (str_end_character == LIT_CHAR_GRAVE_ACCENT) + { + /* Newline (without backslash) is part of the string. + Note: ECMAScript v6, 11.8.6.1 or are both normalized to */ + if (*source_p == LIT_CHAR_CR) + { + status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE; + source_p++; + length++; + if (source_p < source_end_p && *source_p == LIT_CHAR_LF) + { + source_p++; + raw_length_adjust--; + } + line++; + column = 1; + continue; + } + else if (*source_p == LIT_CHAR_LF) + { + source_p++; + length++; + line++; + column = 1; + continue; + } + } + else if (*source_p == LIT_CHAR_CR || *source_p == LIT_CHAR_LF) + { + context_p->token.line = line; + context_p->token.column = column; + parser_raise_error (context_p, PARSER_ERR_NEWLINE_NOT_ALLOWED); + } + + source_p++; + column++; + length++; + + while (source_p < source_end_p && IS_UTF8_INTERMEDIATE_OCTET (*source_p)) + { + source_p++; + length++; + } + } + + if (opts & LEXER_STRING_RAW) + { + length = (size_t) ((source_p - string_start_p) + raw_length_adjust); + } + + if (length > PARSER_MAXIMUM_STRING_LENGTH) + { + parser_raise_error (context_p, PARSER_ERR_STRING_TOO_LONG); + } + + context_p->token.type = ((str_end_character != LIT_CHAR_GRAVE_ACCENT) ? LEXER_LITERAL : LEXER_TEMPLATE_LITERAL); + + /* Fill literal data. */ + context_p->token.lit_location.char_p = string_start_p; + context_p->token.lit_location.length = (prop_length_t) length; + context_p->token.lit_location.type = LEXER_STRING_LITERAL; + context_p->token.lit_location.status_flags = (uint8_t) status_flags; + + context_p->source_p = source_p + 1; + context_p->line = line; + context_p->column = (parser_line_counter_t) (column + 1); +} /* lexer_parse_string */ + +/** + * Check number + */ +static void +lexer_check_numbers (parser_context_t *context_p, /**< context */ + const uint8_t **source_p, /**< source_pointer */ + const uint8_t *source_end_p, /**< end of the source */ + const ecma_char_t digit_max, /**< maximum of the number range */ + const bool is_legacy) /**< is legacy octal number */ +{ + while (true) + { + while (*source_p < source_end_p && *source_p[0] >= LIT_CHAR_0 && *source_p[0] <= digit_max) + { + *source_p += 1; + } + if (*source_p != source_end_p && *source_p[0] == LIT_CHAR_UNDERSCORE) + { + *source_p += 1; + if (is_legacy || *source_p == source_end_p || *source_p[0] == LIT_CHAR_UNDERSCORE || *source_p[0] > digit_max + || *source_p[0] < LIT_CHAR_0) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + continue; + } + + break; + } +} /* lexer_check_numbers */ + +/** + * Parse number. + */ +static void +lexer_parse_number (parser_context_t *context_p) /**< context */ +{ + const uint8_t *source_p = context_p->source_p; + const uint8_t *source_end_p = context_p->source_end_p; + bool can_be_float = false; +#if JERRY_BUILTIN_BIGINT + bool can_be_bigint = true; +#endif /* JERRY_BUILTIN_BIGINT */ + size_t length; + + context_p->token.type = LEXER_LITERAL; + context_p->token.extra_value = LEXER_NUMBER_DECIMAL; + context_p->token.lit_location.char_p = source_p; + context_p->token.lit_location.type = LEXER_NUMBER_LITERAL; + context_p->token.lit_location.status_flags = LEXER_LIT_LOCATION_IS_ASCII; + + if (source_p[0] == LIT_CHAR_0 && source_p + 1 < source_end_p) + { + if (source_p[1] == LIT_CHAR_UNDERSCORE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + + if (LEXER_TO_ASCII_LOWERCASE (source_p[1]) == LIT_CHAR_LOWERCASE_X) + { + context_p->token.extra_value = LEXER_NUMBER_HEXADECIMAL; + source_p += 2; + + if (source_p >= source_end_p || !lit_char_is_hex_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_HEX_DIGIT); + } + + do + { + source_p++; + if (source_p < source_end_p && source_p[0] == LIT_CHAR_UNDERSCORE) + { + source_p++; + if (source_p == source_end_p || !lit_char_is_hex_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + } + } while (source_p < source_end_p && lit_char_is_hex_digit (source_p[0])); + } + else if (LEXER_TO_ASCII_LOWERCASE (source_p[1]) == LIT_CHAR_LOWERCASE_O) + { + context_p->token.extra_value = LEXER_NUMBER_OCTAL; + source_p += 2; + + if (source_p >= source_end_p || !lit_char_is_octal_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_OCTAL_DIGIT); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_7, false); + } + else if (source_p[1] >= LIT_CHAR_0 && source_p[1] <= LIT_CHAR_9) + { + context_p->token.extra_value = LEXER_NUMBER_OCTAL; +#if JERRY_BUILTIN_BIGINT + can_be_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_OCTAL_NUMBER_NOT_ALLOWED); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_7, true); + + if (source_p < source_end_p && source_p[0] >= LIT_CHAR_8 && source_p[0] <= LIT_CHAR_9) + { + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, true); + context_p->token.extra_value = LEXER_NUMBER_DECIMAL; + } + } + + else if (LEXER_TO_ASCII_LOWERCASE (source_p[1]) == LIT_CHAR_LOWERCASE_B) + { + context_p->token.extra_value = LEXER_NUMBER_BINARY; + source_p += 2; + + if (source_p >= source_end_p || !lit_char_is_binary_digit (source_p[0])) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BIN_DIGIT); + } + + do + { + source_p++; + if (source_p < source_end_p && source_p[0] == LIT_CHAR_UNDERSCORE) + { + source_p++; + if (source_p == source_end_p || source_p[0] > LIT_CHAR_9 || source_p[0] < LIT_CHAR_0) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + } + } while (source_p < source_end_p && lit_char_is_binary_digit (source_p[0])); + } + else + { + can_be_float = true; + source_p++; + } + } + else + { + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, false); + can_be_float = true; + } + + if (can_be_float) + { + if (source_p < source_end_p && source_p[0] == LIT_CHAR_DOT) + { + source_p++; +#if JERRY_BUILTIN_BIGINT + can_be_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + if (source_p < source_end_p && source_p[0] == LIT_CHAR_UNDERSCORE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, false); + } + + if (source_p < source_end_p && LEXER_TO_ASCII_LOWERCASE (source_p[0]) == LIT_CHAR_LOWERCASE_E) + { + source_p++; +#if JERRY_BUILTIN_BIGINT + can_be_bigint = false; +#endif /* JERRY_BUILTIN_BIGINT */ + + if (source_p < source_end_p && (source_p[0] == LIT_CHAR_PLUS || source_p[0] == LIT_CHAR_MINUS)) + { + source_p++; + } + + if (source_p >= source_end_p || source_p[0] < LIT_CHAR_0 || source_p[0] > LIT_CHAR_9) + { + parser_raise_error (context_p, PARSER_ERR_MISSING_EXPONENT); + } + + lexer_check_numbers (context_p, &source_p, source_end_p, LIT_CHAR_9, false); + } + } + +#if JERRY_BUILTIN_BIGINT + if (source_p < source_end_p && source_p[0] == LIT_CHAR_LOWERCASE_N) + { + if (!can_be_bigint) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BIGINT); + } + context_p->token.extra_value = LEXER_NUMBER_BIGINT; + source_p++; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + length = (size_t) (source_p - context_p->source_p); + if (length > PARSER_MAXIMUM_STRING_LENGTH) + { + parser_raise_error (context_p, PARSER_ERR_NUMBER_TOO_LONG); + } + + context_p->token.lit_location.length = (prop_length_t) length; + PARSER_PLUS_EQUAL_LC (context_p->column, length); + context_p->source_p = source_p; + + if (source_p < source_end_p && lexer_parse_identifier (context_p, LEXER_PARSE_CHECK_START_AND_RETURN)) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_AFTER_NUMBER); + } +} /* lexer_parse_number */ + +/** + * One character long token (e.g. comma). + * + * @param char1 character + * @param type1 type + */ +#define LEXER_TYPE_A_TOKEN(char1, type1) \ + case (uint8_t) (char1): \ + { \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Token pair, where the first token is prefix of the second (e.g. % and %=). + * + * @param char1 first character + * @param type1 type of the first character + * @param char2 second character + * @param type2 type of the second character + */ +#define LEXER_TYPE_B_TOKEN(char1, type1, char2, type2) \ + case (uint8_t) (char1): \ + { \ + if (length >= 2 && context_p->source_p[1] == (uint8_t) (char2)) \ + { \ + context_p->token.type = (type2); \ + length = 2; \ + break; \ + } \ + \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Three tokens, where the first is the prefix of the other two (e.g. &, &&, &=). + * + * @param char1 first character + * @param type1 type of the first character + * @param char2 second character + * @param type2 type of the second character + * @param char3 third character + * @param type3 type of the third character + */ +#define LEXER_TYPE_C_TOKEN(char1, type1, char2, type2, char3, type3) \ + case (uint8_t) (char1): \ + { \ + if (length >= 2) \ + { \ + if (context_p->source_p[1] == (uint8_t) (char2)) \ + { \ + context_p->token.type = (type2); \ + length = 2; \ + break; \ + } \ + \ + if (context_p->source_p[1] == (uint8_t) (char3)) \ + { \ + context_p->token.type = (type3); \ + length = 2; \ + break; \ + } \ + } \ + \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Four tokens, where the first is the prefix of the other three + * and the second is prefix of the fourth (e.g. &, &&, &=, &&= ). + * + * @param char1 first character + * @param type1 type of the first character + * @param char2 second character + * @param type2 type of the second character + * @param char3 third character + * @param type3 type of the third character + * @param char4 fourth character + * @param type4 type of the fourth character + */ +#define LEXER_TYPE_D_TOKEN(char1, type1, char2, type2, char3, type3, char4, type4) \ + case (uint8_t) (char1): \ + { \ + if (length >= 2) \ + { \ + if (context_p->source_p[1] == (uint8_t) (char2)) \ + { \ + context_p->token.type = (type2); \ + length = 2; \ + break; \ + } \ + \ + if (context_p->source_p[1] == (uint8_t) (char3)) \ + { \ + if (length >= 3 && context_p->source_p[2] == (uint8_t) (char4)) \ + { \ + context_p->token.type = (type4); \ + length = 3; \ + break; \ + } \ + context_p->token.type = (type3); \ + length = 2; \ + break; \ + } \ + } \ + \ + context_p->token.type = (type1); \ + length = 1; \ + break; \ + } + +/** + * Get next token. + */ +void +lexer_next_token (parser_context_t *context_p) /**< context */ +{ + size_t length; + +#if JERRY_FUNCTION_TO_STRING + /* Needed by arrow functions with expression body */ + context_p->function_end_p = context_p->source_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + lexer_skip_spaces (context_p); + + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + length = (size_t) (context_p->source_end_p - context_p->source_p); + if (length == 0) + { + context_p->token.type = LEXER_EOS; + return; + } + + if (lexer_parse_identifier (context_p, LEXER_PARSE_CHECK_KEYWORDS)) + { + return; + } + + if (context_p->source_p[0] >= LIT_CHAR_0 && context_p->source_p[0] <= LIT_CHAR_9) + { + lexer_parse_number (context_p); + return; + } + + switch (context_p->source_p[0]) + { + LEXER_TYPE_A_TOKEN (LIT_CHAR_LEFT_BRACE, LEXER_LEFT_BRACE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_LEFT_PAREN, LEXER_LEFT_PAREN); + LEXER_TYPE_A_TOKEN (LIT_CHAR_LEFT_SQUARE, LEXER_LEFT_SQUARE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_RIGHT_BRACE, LEXER_RIGHT_BRACE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_RIGHT_PAREN, LEXER_RIGHT_PAREN); + LEXER_TYPE_A_TOKEN (LIT_CHAR_RIGHT_SQUARE, LEXER_RIGHT_SQUARE); + LEXER_TYPE_A_TOKEN (LIT_CHAR_SEMICOLON, LEXER_SEMICOLON); + LEXER_TYPE_A_TOKEN (LIT_CHAR_COMMA, LEXER_COMMA); + LEXER_TYPE_A_TOKEN (LIT_CHAR_HASHMARK, LEXER_HASHMARK); + + case (uint8_t) LIT_CHAR_DOT: + { + if (length >= 2 && (context_p->source_p[1] >= LIT_CHAR_0 && context_p->source_p[1] <= LIT_CHAR_9)) + { + lexer_parse_number (context_p); + return; + } + + if (length >= 3 && context_p->source_p[1] == LIT_CHAR_DOT && context_p->source_p[2] == LIT_CHAR_DOT) + { + context_p->token.type = LEXER_THREE_DOTS; + length = 3; + break; + } + + context_p->token.type = LEXER_DOT; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_LESS_THAN: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_LESS_EQUAL; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_LESS_THAN) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_LEFT_SHIFT; + length = 3; + break; + } + + context_p->token.type = LEXER_LEFT_SHIFT; + length = 2; + break; + } + } + + context_p->token.type = LEXER_LESS; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_GREATER_THAN: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_GREATER_EQUAL; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + if (length >= 3) + { + if (context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_RIGHT_SHIFT; + length = 3; + break; + } + + if (context_p->source_p[2] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + if (length >= 4 && context_p->source_p[3] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_UNS_RIGHT_SHIFT; + length = 4; + break; + } + + context_p->token.type = LEXER_UNS_RIGHT_SHIFT; + length = 3; + break; + } + } + + context_p->token.type = LEXER_RIGHT_SHIFT; + length = 2; + break; + } + } + + context_p->token.type = LEXER_GREATER; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_EQUALS: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_STRICT_EQUAL; + length = 3; + break; + } + + context_p->token.type = LEXER_EQUAL; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + context_p->token.type = LEXER_ARROW; + length = 2; + break; + } + } + + context_p->token.type = LEXER_ASSIGN; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_EXCLAMATION: + { + if (length >= 2 && context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_STRICT_NOT_EQUAL; + length = 3; + break; + } + + context_p->token.type = LEXER_NOT_EQUAL; + length = 2; + break; + } + + context_p->token.type = LEXER_LOGICAL_NOT; + length = 1; + break; + } + + LEXER_TYPE_C_TOKEN (LIT_CHAR_PLUS, LEXER_ADD, LIT_CHAR_EQUALS, LEXER_ASSIGN_ADD, LIT_CHAR_PLUS, LEXER_INCREASE) + LEXER_TYPE_C_TOKEN (LIT_CHAR_MINUS, + LEXER_SUBTRACT, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_SUBTRACT, + LIT_CHAR_MINUS, + LEXER_DECREASE) + + case (uint8_t) LIT_CHAR_ASTERISK: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_MULTIPLY; + length = 2; + break; + } + + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_ASTERISK) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_EXPONENTIATION; + length = 3; + break; + } + + context_p->token.type = LEXER_EXPONENTIATION; + length = 2; + break; + } + } + + context_p->token.type = LEXER_MULTIPLY; + length = 1; + break; + } + + LEXER_TYPE_B_TOKEN (LIT_CHAR_SLASH, LEXER_DIVIDE, LIT_CHAR_EQUALS, LEXER_ASSIGN_DIVIDE) + LEXER_TYPE_B_TOKEN (LIT_CHAR_PERCENT, LEXER_MODULO, LIT_CHAR_EQUALS, LEXER_ASSIGN_MODULO) + + LEXER_TYPE_D_TOKEN (LIT_CHAR_AMPERSAND, + LEXER_BIT_AND, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_BIT_AND, + LIT_CHAR_AMPERSAND, + LEXER_LOGICAL_AND, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_LOGICAL_AND) + LEXER_TYPE_D_TOKEN (LIT_CHAR_VLINE, + LEXER_BIT_OR, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_BIT_OR, + LIT_CHAR_VLINE, + LEXER_LOGICAL_OR, + LIT_CHAR_EQUALS, + LEXER_ASSIGN_LOGICAL_OR) + + LEXER_TYPE_B_TOKEN (LIT_CHAR_CIRCUMFLEX, LEXER_BIT_XOR, LIT_CHAR_EQUALS, LEXER_ASSIGN_BIT_XOR) + + LEXER_TYPE_A_TOKEN (LIT_CHAR_TILDE, LEXER_BIT_NOT); + case (uint8_t) (LIT_CHAR_QUESTION): + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_QUESTION) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_ASSIGN_NULLISH_COALESCING; + length = 3; + break; + } + context_p->token.type = LEXER_NULLISH_COALESCING; + length = 2; + break; + } + } + + context_p->token.type = LEXER_QUESTION_MARK; + length = 1; + break; + } + + LEXER_TYPE_A_TOKEN (LIT_CHAR_COLON, LEXER_COLON); + + case LIT_CHAR_SINGLE_QUOTE: + case LIT_CHAR_DOUBLE_QUOTE: + case LIT_CHAR_GRAVE_ACCENT: + { + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + return; + } + + default: + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + } + + context_p->source_p += length; + PARSER_PLUS_EQUAL_LC (context_p->column, length); +} /* lexer_next_token */ + +#undef LEXER_TYPE_A_TOKEN +#undef LEXER_TYPE_B_TOKEN +#undef LEXER_TYPE_C_TOKEN +#undef LEXER_TYPE_D_TOKEN + +/** + * Checks whether the next token starts with the specified character. + * + * @return true - if the next is the specified character + * false - otherwise + */ +bool +lexer_check_next_character (parser_context_t *context_p, /**< context */ + lit_utf8_byte_t character) /**< specified character */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + return (context_p->source_p < context_p->source_end_p && context_p->source_p[0] == (uint8_t) character); +} /* lexer_check_next_character */ + +/** + * Checks whether the next token starts with either specified characters. + * + * @return true - if the next is the specified character + * false - otherwise + */ +bool +lexer_check_next_characters (parser_context_t *context_p, /**< context */ + lit_utf8_byte_t character1, /**< first alternative character */ + lit_utf8_byte_t character2) /**< second alternative character */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + return (context_p->source_p < context_p->source_end_p + && (context_p->source_p[0] == (uint8_t) character1 || context_p->source_p[0] == (uint8_t) character2)); +} /* lexer_check_next_characters */ + +/** + * Consumes the next character. The character cannot be a white space. + * + * @return consumed character + */ +uint8_t +lexer_consume_next_character (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->source_p < context_p->source_end_p); + + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + + PARSER_PLUS_EQUAL_LC (context_p->column, 1); + return *context_p->source_p++; +} /* lexer_consume_next_character */ + +/** + * Checks whether the next character can be the start of a post primary expression + * + * Note: + * the result is not precise, but this inprecise result + * has no side effects for negating number literals + * + * @return true if the next character can be the start of a post primary expression + */ +bool +lexer_check_post_primary_exp (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + if (context_p->source_p >= context_p->source_end_p) + { + return false; + } + + switch (context_p->source_p[0]) + { + case LIT_CHAR_DOT: + case LIT_CHAR_LEFT_PAREN: + case LIT_CHAR_LEFT_SQUARE: + case LIT_CHAR_GRAVE_ACCENT: + { + return true; + } + case LIT_CHAR_PLUS: + case LIT_CHAR_MINUS: + { + return (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->source_p + 1 < context_p->source_end_p + && context_p->source_p[1] == context_p->source_p[0]); + } + case LIT_CHAR_ASTERISK: + { + return (context_p->source_p + 1 < context_p->source_end_p + && context_p->source_p[1] == (uint8_t) LIT_CHAR_ASTERISK); + } + } + + return false; +} /* lexer_check_post_primary_exp */ + +/** + * Checks whether the next token is a type used for detecting arrow functions. + * + * @return true if the next token is an arrow token + */ +bool +lexer_check_arrow (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + return (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->source_p + 2 <= context_p->source_end_p + && context_p->source_p[0] == (uint8_t) LIT_CHAR_EQUALS + && context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN); +} /* lexer_check_arrow */ + +/** + * Checks whether the next token is a comma or equal sign. + * + * @return true if the next token is a comma or equal sign + */ +bool +lexer_check_arrow_param (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.flags & LEXER_NO_SKIP_SPACES); + + if (context_p->source_p >= context_p->source_end_p) + { + return false; + } + + if (context_p->source_p[0] == LIT_CHAR_COMMA) + { + return true; + } + + if (context_p->source_p[0] != LIT_CHAR_EQUALS) + { + return false; + } + + return (context_p->source_p + 1 >= context_p->source_end_p || context_p->source_p[1] != LIT_CHAR_EQUALS); +} /* lexer_check_arrow_param */ + +/** + * Checks whether the yield expression has no argument. + * + * @return true if it has no argument + */ +bool +lexer_check_yield_no_arg (parser_context_t *context_p) /**< context */ +{ + if (context_p->token.flags & LEXER_WAS_NEWLINE) + { + return true; + } + + switch (context_p->token.type) + { + case LEXER_RIGHT_BRACE: + case LEXER_RIGHT_PAREN: + case LEXER_RIGHT_SQUARE: + case LEXER_COMMA: + case LEXER_COLON: + case LEXER_SEMICOLON: + case LEXER_EOS: + { + return true; + } + default: + { + return false; + } + } +} /* lexer_check_yield_no_arg */ + +/** + * Checks whether the next token is a multiply and consumes it. + * + * @return true if the next token is a multiply + */ +bool +lexer_consume_generator (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + if (context_p->source_p >= context_p->source_end_p || context_p->source_p[0] != LIT_CHAR_ASTERISK + || (context_p->source_p + 1 < context_p->source_end_p + && (context_p->source_p[1] == LIT_CHAR_EQUALS || context_p->source_p[1] == LIT_CHAR_ASTERISK))) + { + return false; + } + + lexer_consume_next_character (context_p); + context_p->token.type = LEXER_MULTIPLY; + return true; +} /* lexer_consume_generator */ + +/** + * Checks whether the next token is an equal sign and consumes it. + * + * @return true if the next token is an equal sign + */ +bool +lexer_consume_assign (parser_context_t *context_p) /**< context */ +{ + if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + } + + if (context_p->source_p >= context_p->source_end_p || context_p->source_p[0] != LIT_CHAR_EQUALS + || (context_p->source_p + 1 < context_p->source_end_p + && (context_p->source_p[1] == LIT_CHAR_EQUALS || context_p->source_p[1] == LIT_CHAR_GREATER_THAN))) + { + return false; + } + + lexer_consume_next_character (context_p); + context_p->token.type = LEXER_ASSIGN; + return true; +} /* lexer_consume_assign */ + +/** + * Update await / yield keywords after an arrow function with expression. + */ +void +lexer_update_await_yield (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< parser status flags after restore */ +{ + if (!(status_flags & PARSER_IS_STRICT)) + { + if (status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + if (context_p->token.type == LEXER_LITERAL && context_p->token.keyword_type == LEXER_KEYW_YIELD) + { + context_p->token.type = LEXER_KEYW_YIELD; + } + } + else + { + if (context_p->token.type == LEXER_KEYW_YIELD) + { + JERRY_ASSERT (context_p->token.keyword_type == LEXER_KEYW_YIELD); + context_p->token.type = LEXER_LITERAL; + } + } + } + + if (!(context_p->global_status_flags & ECMA_PARSE_MODULE)) + { + if (status_flags & PARSER_IS_ASYNC_FUNCTION) + { + if (context_p->token.type == LEXER_LITERAL && context_p->token.keyword_type == LEXER_KEYW_AWAIT) + { + context_p->token.type = LEXER_KEYW_AWAIT; + } + } + else + { + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + JERRY_ASSERT (context_p->token.keyword_type == LEXER_KEYW_AWAIT); + context_p->token.type = LEXER_LITERAL; + } + } + } +} /* lexer_update_await_yield */ + +/** + * Read next token without skipping whitespaces and checking keywords + * + * @return true if the next literal is private identifier, false otherwise + */ +bool +lexer_scan_private_identifier (parser_context_t *context_p) /**< context */ +{ + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + return (context_p->source_p < context_p->source_end_p && lexer_parse_identifier (context_p, LEXER_PARSE_NO_OPTS)); +} /* lexer_scan_private_identifier */ + +/** + * Convert an ident with escapes to a utf8 string. + */ +void +lexer_convert_ident_to_cesu8 (uint8_t *destination_p, /**< destination string */ + const uint8_t *source_p, /**< source string */ + prop_length_t length) /**< length of destination string */ +{ + const uint8_t *destination_end_p = destination_p + length; + + JERRY_ASSERT (length <= PARSER_MAXIMUM_IDENT_LENGTH); + + do + { + if (*source_p == LIT_CHAR_BACKSLASH) + { + source_p += 2; + destination_p += lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (&source_p)); + continue; + } + + if (*source_p >= LIT_UTF8_4_BYTE_MARKER) + { + lit_four_byte_utf8_char_to_cesu8 (destination_p, source_p); + + destination_p += 6; + source_p += 4; + continue; + } + + *destination_p++ = *source_p++; + } while (destination_p < destination_end_p); +} /* lexer_convert_ident_to_cesu8 */ + +/** + * Convert literal to character sequence + */ +const uint8_t * +lexer_convert_literal_to_chars (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *literal_p, /**< literal location */ + uint8_t *local_byte_array_p, /**< local byte array to store chars */ + lexer_string_options_t opts) /**< options */ +{ + JERRY_ASSERT (context_p->u.allocated_buffer_p == NULL); + + if (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return literal_p->char_p; + } + + uint8_t *destination_start_p; + if (literal_p->length > LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE) + { + context_p->u.allocated_buffer_p = (uint8_t *) parser_malloc_local (context_p, literal_p->length); + context_p->allocated_buffer_size = literal_p->length; + destination_start_p = (uint8_t*) context_p->u.allocated_buffer_p; + } + else + { + destination_start_p = local_byte_array_p; + } + + if (literal_p->type == LEXER_IDENT_LITERAL) + { + lexer_convert_ident_to_cesu8 (destination_start_p, literal_p->char_p, literal_p->length); + return destination_start_p; + } + + const uint8_t *source_p = literal_p->char_p; + uint8_t *destination_p = destination_start_p; + + uint8_t str_end_character = source_p[-1]; + + if (str_end_character == LIT_CHAR_RIGHT_BRACE) + { + str_end_character = LIT_CHAR_GRAVE_ACCENT; + } + + bool is_raw = (opts & LEXER_STRING_RAW) != 0; + + while (true) + { + if (*source_p == str_end_character) + { + break; + } + + if (*source_p == LIT_CHAR_BACKSLASH && !is_raw) + { + uint8_t conv_character; + + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + /* Newline is ignored. */ + if (*source_p == LIT_CHAR_CR) + { + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p == LIT_CHAR_LF) + { + source_p++; + } + continue; + } + else if (*source_p == LIT_CHAR_LF) + { + source_p++; + continue; + } + else if (*source_p == LEXER_NEWLINE_LS_PS_BYTE_1 && LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + source_p += 3; + continue; + } + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_3) + { + lit_code_point_t octal_number = (uint32_t) (*source_p - LIT_CHAR_0); + + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + octal_number = octal_number * 8 + (uint32_t) (*source_p - LIT_CHAR_0); + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + octal_number = octal_number * 8 + (uint32_t) (*source_p - LIT_CHAR_0); + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + } + } + + destination_p += lit_code_point_to_cesu8_bytes (destination_p, octal_number); + continue; + } + + if (*source_p >= LIT_CHAR_4 && *source_p <= LIT_CHAR_7) + { + uint32_t octal_number = (uint32_t) (*source_p - LIT_CHAR_0); + + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + + if (*source_p >= LIT_CHAR_0 && *source_p <= LIT_CHAR_7) + { + octal_number = octal_number * 8 + (uint32_t) (*source_p - LIT_CHAR_0); + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + } + + *destination_p++ = (uint8_t) octal_number; + continue; + } + + if (*source_p == LIT_CHAR_LOWERCASE_X || *source_p == LIT_CHAR_LOWERCASE_U) + { + source_p++; + destination_p += lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (&source_p)); + continue; + } + + conv_character = *source_p; + switch (*source_p) + { + case LIT_CHAR_LOWERCASE_B: + { + conv_character = 0x08; + break; + } + case LIT_CHAR_LOWERCASE_T: + { + conv_character = 0x09; + break; + } + case LIT_CHAR_LOWERCASE_N: + { + conv_character = 0x0a; + break; + } + case LIT_CHAR_LOWERCASE_V: + { + conv_character = 0x0b; + break; + } + case LIT_CHAR_LOWERCASE_F: + { + conv_character = 0x0c; + break; + } + case LIT_CHAR_LOWERCASE_R: + { + conv_character = 0x0d; + break; + } + } + + if (conv_character != *source_p) + { + *destination_p++ = conv_character; + source_p++; + continue; + } + } + else if (str_end_character == LIT_CHAR_GRAVE_ACCENT) + { + if (source_p[0] == LIT_CHAR_DOLLAR_SIGN && source_p[1] == LIT_CHAR_LEFT_BRACE) + { + source_p++; + JERRY_ASSERT (source_p < context_p->source_end_p); + break; + } + if (*source_p == LIT_CHAR_CR) + { + *destination_p++ = LIT_CHAR_LF; + source_p++; + if (*source_p != str_end_character && *source_p == LIT_CHAR_LF) + { + source_p++; + } + continue; + } + if ((*source_p == LIT_CHAR_BACKSLASH) && is_raw) + { + JERRY_ASSERT (source_p + 1 < context_p->source_end_p); + if ((*(source_p + 1) == LIT_CHAR_GRAVE_ACCENT) || (*(source_p + 1) == LIT_CHAR_BACKSLASH)) + { + *destination_p++ = *source_p++; + *destination_p++ = *source_p++; + continue; + } + } + } + + if (*source_p >= LIT_UTF8_4_BYTE_MARKER) + { + /* Processing 4 byte unicode sequence (even if it is + * after a backslash). Always converted to two 3 byte + * long sequence. */ + lit_four_byte_utf8_char_to_cesu8 (destination_p, source_p); + + destination_p += 6; + source_p += 4; + continue; + } + + *destination_p++ = *source_p++; + + /* There is no need to check the source_end_p + * since the string is terminated by a quotation mark. */ + while (IS_UTF8_INTERMEDIATE_OCTET (*source_p)) + { + *destination_p++ = *source_p++; + } + } + + JERRY_ASSERT (destination_p == destination_start_p + literal_p->length); + + return destination_start_p; +} /* lexer_convert_literal_to_chars */ + +/** + * Construct an unused literal. + * + * @return a newly allocated literal + */ +lexer_literal_t * +lexer_construct_unused_literal (parser_context_t *context_p) /**< context */ +{ + lexer_literal_t *literal_p; + + if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->type = LEXER_UNUSED_LITERAL; + literal_p->status_flags = 0; + return literal_p; +} /* lexer_construct_unused_literal */ + +/** + * Construct a literal object from an identifier. + */ +void +lexer_construct_literal_object (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *lit_location_p, /**< literal location */ + uint8_t literal_type) /**< final literal type */ +{ + uint8_t local_byte_array[LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE]; + + const uint8_t *char_p = + lexer_convert_literal_to_chars (context_p, lit_location_p, local_byte_array, LEXER_STRING_NO_OPTS); + + size_t length = lit_location_p->length; + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + uint32_t literal_index = 0; + bool search_scope_stack = (literal_type == LEXER_IDENT_LITERAL); + + if (JERRY_UNLIKELY (literal_type == LEXER_NEW_IDENT_LITERAL)) + { + literal_type = LEXER_IDENT_LITERAL; + } + + JERRY_ASSERT (literal_type == LEXER_IDENT_LITERAL || literal_type == LEXER_STRING_LITERAL); + + JERRY_ASSERT (literal_type != LEXER_IDENT_LITERAL || length <= PARSER_MAXIMUM_IDENT_LENGTH); + JERRY_ASSERT (literal_type != LEXER_STRING_LITERAL || length <= PARSER_MAXIMUM_STRING_LENGTH); + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->type == literal_type && literal_p->prop.length == length + && memcmp (literal_p->u.char_p, char_p, length) == 0) + { + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + + parser_free_allocated_buffer (context_p); + + if (search_scope_stack) + { + parser_scope_stack_t *scope_stack_start_p = context_p->scope_stack_p; + parser_scope_stack_t *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top; + + while (scope_stack_p > scope_stack_start_p) + { + scope_stack_p--; + + if (scope_stack_p->map_from == literal_index) + { + JERRY_ASSERT (scanner_decode_map_to (scope_stack_p) >= PARSER_REGISTER_START + || (literal_p->status_flags & LEXER_FLAG_USED)); + context_p->lit_object.index = scanner_decode_map_to (scope_stack_p); + return; + } + } + + literal_p->status_flags |= LEXER_FLAG_USED; + } + return; + } + + literal_index++; + } + + JERRY_ASSERT (literal_index == context_p->literal_count); + + if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->prop.length = (prop_length_t) length; + literal_p->type = literal_type; + + uint8_t status_flags = LEXER_FLAG_SOURCE_PTR; + + if (length > 0 && char_p == local_byte_array) + { + literal_p->u.char_p = (uint8_t *) jmem_heap_alloc_block (length); + memcpy ((uint8_t *) literal_p->u.char_p, char_p, length); + status_flags = 0; + } + else + { + literal_p->u.char_p = char_p; + + /* Buffer is taken over when a new literal is constructed. */ + if (context_p->u.allocated_buffer_p != NULL) + { + JERRY_ASSERT (char_p == context_p->u.allocated_buffer_p); + + context_p->u.allocated_buffer_p = NULL; + status_flags = 0; + } + } + + if (search_scope_stack) + { + status_flags |= LEXER_FLAG_USED; + } + + if (lit_location_p->status_flags & LEXER_LIT_LOCATION_IS_ASCII) + { + literal_p->status_flags |= LEXER_FLAG_ASCII; + } + + literal_p->status_flags = status_flags; + + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + context_p->literal_count++; + + JERRY_ASSERT (context_p->u.allocated_buffer_p == NULL); +} /* lexer_construct_literal_object */ + +/** + * Construct a number object. + * + * @return true if number is small number + */ +bool +lexer_construct_number_object (parser_context_t *context_p, /**< context */ + bool is_expr, /**< expression is parsed */ + bool is_negative_number) /**< sign is negative */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + ecma_value_t lit_value; + uint32_t literal_index = 0; + prop_length_t length = context_p->token.lit_location.length; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (context_p->token.extra_value != LEXER_NUMBER_BIGINT)) + { +#endif /* JERRY_BUILTIN_BIGINT */ + ecma_number_t num; + uint32_t options = ECMA_CONVERSION_ALLOW_UNDERSCORE; + + if (context_p->token.extra_value == LEXER_NUMBER_OCTAL) + { + num = ecma_utf8_string_to_number_by_radix (context_p->token.lit_location.char_p, length, 8, options); + } + else + { + num = ecma_utf8_string_to_number (context_p->token.lit_location.char_p, length, options); + } + + if (is_expr) + { + int32_t int_num = (int32_t) num; + + if (int_num == num && int_num <= CBC_PUSH_NUMBER_BYTE_RANGE_END && (int_num != 0 || !is_negative_number)) + { + context_p->lit_object.index = (uint16_t) int_num; + return true; + } + } + + if (is_negative_number) + { + num = -num; + } + + lit_value = ecma_find_or_create_literal_number (num); +#if JERRY_BUILTIN_BIGINT + } + else + { + uint32_t options = (ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR | ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR + | ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE); + + if (is_negative_number) + { + options |= ECMA_BIGINT_PARSE_SET_NEGATIVE; + } + + JERRY_ASSERT (length >= 2); + lit_value = + ecma_bigint_parse_string (context_p->token.lit_location.char_p, (lit_utf8_size_t) (length - 1), options); + + JERRY_ASSERT (lit_value != ECMA_VALUE_FALSE && !ECMA_IS_VALUE_ERROR (lit_value)); + + if (lit_value == ECMA_VALUE_NULL) + { + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + + lit_value = ecma_find_or_create_literal_bigint (lit_value); + } +#endif /* JERRY_BUILTIN_BIGINT */ + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->type == LEXER_NUMBER_LITERAL && literal_p->u.value == lit_value) + { + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + return false; + } + + literal_index++; + } + + JERRY_ASSERT (literal_index == context_p->literal_count); + + if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->u.value = lit_value; + literal_p->prop.length = 0; /* Unused. */ + literal_p->type = LEXER_NUMBER_LITERAL; + literal_p->status_flags = 0; + + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + + context_p->literal_count++; + return false; +} /* lexer_construct_number_object */ + +/** + * Convert a push number opcode to push literal opcode + */ +void +lexer_convert_push_number_to_push_literal (parser_context_t *context_p) /**< context */ +{ + ecma_integer_value_t value; + bool two_literals = context_p->last_cbc_opcode >= CBC_PUSH_LITERAL_PUSH_NUMBER_0; + + if (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_0 || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_0) + { + value = 0; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_POS_BYTE + || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) + { + value = ((ecma_integer_value_t) context_p->last_cbc.value) + 1; + } + else + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_NEG_BYTE + || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE); + value = -((ecma_integer_value_t) context_p->last_cbc.value) - 1; + } + + ecma_value_t lit_value = ecma_make_integer_value (value); + + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + context_p->last_cbc_opcode = two_literals ? CBC_PUSH_TWO_LITERALS : CBC_PUSH_LITERAL; + + uint32_t literal_index = 0; + lexer_literal_t *literal_p; + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->type == LEXER_NUMBER_LITERAL && literal_p->u.value == lit_value) + { + if (two_literals) + { + context_p->last_cbc.value = (uint16_t) literal_index; + } + else + { + context_p->last_cbc.literal_index = (uint16_t) literal_index; + } + return; + } + + literal_index++; + } + + JERRY_ASSERT (literal_index == context_p->literal_count); + + if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->u.value = lit_value; + literal_p->prop.length = 0; /* Unused. */ + literal_p->type = LEXER_NUMBER_LITERAL; + literal_p->status_flags = 0; + + context_p->literal_count++; + + if (two_literals) + { + context_p->last_cbc.value = (uint16_t) literal_index; + } + else + { + context_p->last_cbc.literal_index = (uint16_t) literal_index; + } +} /* lexer_convert_push_number_to_push_literal */ + +/** + * Construct a function literal object. + * + * @return function object literal index + */ +uint16_t +lexer_construct_function_object (parser_context_t *context_p, /**< context */ + uint32_t extra_status_flags) /**< extra status flags */ +{ +#if (JERRY_STACK_LIMIT != 0) + if (JERRY_UNLIKELY (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT)) + { + parser_raise_error (context_p, PARSER_ERR_STACK_OVERFLOW); + } +#endif /* JERRY_STACK_LIMIT != 0 */ + ecma_compiled_code_t *compiled_code_p; + lexer_literal_t *literal_p; + uint16_t result_index; + + if (context_p->status_flags & PARSER_INSIDE_WITH) + { + extra_status_flags |= PARSER_INSIDE_WITH; + } + + literal_p = lexer_construct_unused_literal (context_p); + result_index = context_p->literal_count; + context_p->literal_count++; + + parser_flush_cbc (context_p); + + if (JERRY_LIKELY (!(extra_status_flags & PARSER_IS_ARROW_FUNCTION))) + { + compiled_code_p = parser_parse_function (context_p, extra_status_flags); + } + else + { + compiled_code_p = parser_parse_arrow_function (context_p, extra_status_flags); + } + + literal_p->u.bytecode_p = compiled_code_p; + literal_p->type = LEXER_FUNCTION_LITERAL; + + return result_index; +} /* lexer_construct_function_object */ + +/** + * Construct a class static block function literal object. + * + * @return function object literal index + */ +uint16_t +lexer_construct_class_static_block_function (parser_context_t *context_p) /**< context */ +{ + ecma_compiled_code_t *compiled_code_p; + lexer_literal_t *literal_p; + uint16_t result_index; + + literal_p = lexer_construct_unused_literal (context_p); + result_index = context_p->literal_count; + context_p->literal_count++; + + parser_flush_cbc (context_p); + compiled_code_p = parser_parse_class_static_block (context_p); + + literal_p->u.bytecode_p = compiled_code_p; + literal_p->type = LEXER_FUNCTION_LITERAL; + + return result_index; +} /* lexer_construct_class_static_block_function */ + +/** + * Construct a regular expression object. + * + * Note: In ESNEXT the constructed literal's type can be LEXER_STRING_LITERAL which represents + * invalid pattern. In this case the lit_object's index contains the thrown error message literal. + * Otherwise a new literal is appended to the end of the literal pool. + */ +void +lexer_construct_regexp_object (parser_context_t *context_p, /**< context */ + bool parse_only) /**< parse only */ +{ +#if JERRY_BUILTIN_REGEXP + const uint8_t *source_p = context_p->source_p; + const uint8_t *regex_start_p = context_p->source_p; + const uint8_t *regex_end_p = regex_start_p; + const uint8_t *source_end_p = context_p->source_end_p; + parser_line_counter_t column = context_p->column; + bool in_class = false; + uint16_t current_flags; + lit_utf8_size_t length; + + JERRY_ASSERT (context_p->token.type == LEXER_DIVIDE || context_p->token.type == LEXER_ASSIGN_DIVIDE); + + if (context_p->token.type == LEXER_ASSIGN_DIVIDE) + { + regex_start_p--; + } + + while (true) + { + if (source_p >= source_end_p) + { + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_REGEXP); + } + + if (!in_class && source_p[0] == LIT_CHAR_SLASH) + { + regex_end_p = source_p; + source_p++; + column++; + break; + } + + switch (source_p[0]) + { + case LIT_CHAR_CR: + case LIT_CHAR_LF: + case LEXER_NEWLINE_LS_PS_BYTE_1: + { + if (source_p[0] != LEXER_NEWLINE_LS_PS_BYTE_1 || LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) + { + parser_raise_error (context_p, PARSER_ERR_NEWLINE_NOT_ALLOWED); + } + break; + } + case LIT_CHAR_TAB: + { + column = align_column_to_tab (column); + /* Subtract -1 because column is increased below. */ + column--; + break; + } + case LIT_CHAR_LEFT_SQUARE: + { + in_class = true; + break; + } + case LIT_CHAR_RIGHT_SQUARE: + { + in_class = false; + break; + } + case LIT_CHAR_BACKSLASH: + { + if (source_p + 1 >= source_end_p) + { + parser_raise_error (context_p, PARSER_ERR_UNTERMINATED_REGEXP); + } + + if (source_p[1] >= 0x20 && source_p[1] <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) + { + source_p++; + column++; + } + } + } + + source_p++; + column++; + + while (source_p < source_end_p && IS_UTF8_INTERMEDIATE_OCTET (source_p[0])) + { + source_p++; + } + } + + current_flags = 0; + while (source_p < source_end_p) + { + uint32_t flag = 0; + + if (source_p[0] == LIT_CHAR_LOWERCASE_G) + { + flag = RE_FLAG_GLOBAL; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_I) + { + flag = RE_FLAG_IGNORE_CASE; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_M) + { + flag = RE_FLAG_MULTILINE; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_U) + { + flag = RE_FLAG_UNICODE; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_Y) + { + flag = RE_FLAG_STICKY; + } + else if (source_p[0] == LIT_CHAR_LOWERCASE_S) + { + flag = RE_FLAG_DOTALL; + } + + if (flag == 0) + { + break; + } + + if (current_flags & flag) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_REGEXP_FLAG); + } + + current_flags = (uint16_t) (current_flags | flag); + source_p++; + column++; + } + + context_p->source_p = source_p; + context_p->column = column; + + if (source_p < source_end_p && lexer_parse_identifier (context_p, LEXER_PARSE_CHECK_PART_AND_RETURN)) + { + parser_raise_error (context_p, PARSER_ERR_UNKNOWN_REGEXP_FLAG); + } + + length = (lit_utf8_size_t) (regex_end_p - regex_start_p); + if (length > PARSER_MAXIMUM_STRING_LENGTH) + { + parser_raise_error (context_p, PARSER_ERR_REGEXP_TOO_LONG); + } + + context_p->column = column; + context_p->source_p = source_p; + + if (parse_only) + { + return; + } + + if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + /* Compile the RegExp literal and store the RegExp bytecode pointer */ + ecma_string_t *pattern_str_p = NULL; + + if (lit_is_valid_cesu8_string (regex_start_p, length)) + { + pattern_str_p = ecma_new_ecma_string_from_utf8 (regex_start_p, length); + } + else + { + JERRY_ASSERT (lit_is_valid_utf8_string (regex_start_p, length, false)); + pattern_str_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (regex_start_p, length); + } + + re_compiled_code_t *re_bytecode_p = re_compile_bytecode (pattern_str_p, current_flags); + ecma_deref_ecma_string (pattern_str_p); + + if (JERRY_UNLIKELY (re_bytecode_p == NULL)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_REGEXP); + } + + lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->u.bytecode_p = (ecma_compiled_code_t *) re_bytecode_p; + literal_p->type = LEXER_REGEXP_LITERAL; + literal_p->prop.length = (prop_length_t) length; + literal_p->status_flags = 0; + + context_p->token.type = LEXER_LITERAL; + context_p->token.lit_location.type = LEXER_REGEXP_LITERAL; + + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = context_p->literal_count++; +#else /* !JERRY_BUILTIN_REGEXP */ + JERRY_UNUSED (parse_only); + parser_raise_error (context_p, PARSER_ERR_UNSUPPORTED_REGEXP); +#endif /* JERRY_BUILTIN_REGEXP */ +} /* lexer_construct_regexp_object */ + +/** + * Next token must be an identifier. + */ +void +lexer_expect_identifier (parser_context_t *context_p, /**< context */ + uint8_t literal_type) /**< literal type */ +{ + JERRY_ASSERT (literal_type == LEXER_STRING_LITERAL || literal_type == LEXER_IDENT_LITERAL + || literal_type == LEXER_NEW_IDENT_LITERAL); + + lexer_skip_spaces (context_p); + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + if (context_p->source_p < context_p->source_end_p + && lexer_parse_identifier ( + context_p, + (literal_type != LEXER_STRING_LITERAL ? LEXER_PARSE_CHECK_KEYWORDS : LEXER_PARSE_NO_OPTS))) + { + if (context_p->token.type == LEXER_LITERAL) + { + JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, literal_type); + + if (literal_type != LEXER_STRING_LITERAL && (context_p->status_flags & PARSER_IS_STRICT)) + { + if (context_p->token.keyword_type == LEXER_KEYW_EVAL) + { + parser_raise_error (context_p, PARSER_ERR_EVAL_NOT_ALLOWED); + } + else if (context_p->token.keyword_type == LEXER_KEYW_ARGUMENTS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_NOT_ALLOWED); + } + } + return; + } + } +#if JERRY_MODULE_SYSTEM + else if (context_p->status_flags & PARSER_MODULE_DEFAULT_CLASS_OR_FUNC) + { + /* When parsing default exports for modules, it is not required by functions or classes to have identifiers. + * In this case we use a synthetic name for them. */ + context_p->token.type = LEXER_LITERAL; + context_p->token.lit_location = lexer_default_literal; + lexer_construct_literal_object (context_p, &context_p->token.lit_location, literal_type); + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC); + return; + } +#endif /* JERRY_MODULE_SYSTEM */ + if (context_p->token.type == LEXER_KEYW_YIELD) + { + parser_raise_error (context_p, PARSER_ERR_YIELD_NOT_ALLOWED); + } + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED); + } + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); +} /* lexer_expect_identifier */ + +/** + * Next token must be an identifier. + */ +void +lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ + uint32_t ident_opts) /**< lexer_obj_ident_opts_t option bits */ +{ + lexer_skip_spaces (context_p); + + if (context_p->source_p >= context_p->source_end_p) + { + parser_raise_error (context_p, PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED); + } + + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + bool create_literal_object = false; + + JERRY_ASSERT ((ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER) || !(ident_opts & LEXER_OBJ_IDENT_CLASS_NO_STATIC)); + +#if JERRY_FUNCTION_TO_STRING + if (ident_opts & LEXER_OBJ_IDENT_SET_FUNCTION_START) + { + context_p->function_start_p = context_p->source_p; + } +#endif /* JERRY_FUNCTION_TO_STRING */ + + if (lexer_parse_identifier (context_p, LEXER_PARSE_NO_OPTS)) + { + if (!(ident_opts & (LEXER_OBJ_IDENT_ONLY_IDENTIFIERS | LEXER_OBJ_IDENT_OBJECT_PATTERN))) + { + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + + if (context_p->source_p < context_p->source_end_p && context_p->source_p[0] != LIT_CHAR_COMMA + && context_p->source_p[0] != LIT_CHAR_RIGHT_BRACE && context_p->source_p[0] != LIT_CHAR_LEFT_PAREN + && context_p->source_p[0] != LIT_CHAR_SEMICOLON && context_p->source_p[0] != LIT_CHAR_EQUALS + && context_p->source_p[0] != LIT_CHAR_COLON) + { + if (lexer_compare_literal_to_string (context_p, "get", 3)) + { + context_p->token.type = LEXER_PROPERTY_GETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "set", 3)) + { + context_p->token.type = LEXER_PROPERTY_SETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "async", 5)) + { + context_p->token.type = LEXER_KEYW_ASYNC; + return; + } + + if (ident_opts & LEXER_OBJ_IDENT_CLASS_NO_STATIC) + { + if (lexer_compare_literal_to_string (context_p, "static", 6)) + { + context_p->token.type = LEXER_KEYW_STATIC; + } + return; + } + } + } + + create_literal_object = true; + } + else if (ident_opts & LEXER_OBJ_IDENT_CLASS_PRIVATE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + else + { + switch (context_p->source_p[0]) + { + case LIT_CHAR_DOUBLE_QUOTE: + case LIT_CHAR_SINGLE_QUOTE: + { + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + create_literal_object = true; + break; + } + case LIT_CHAR_LEFT_SQUARE: + { +#if JERRY_FUNCTION_TO_STRING + const uint8_t *function_start_p = context_p->function_start_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + lexer_consume_next_character (context_p); + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_SQUARE_EXPECTED); + } + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = function_start_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + return; + } + case LIT_CHAR_ASTERISK: + { + if (ident_opts & (LEXER_OBJ_IDENT_ONLY_IDENTIFIERS | LEXER_OBJ_IDENT_OBJECT_PATTERN)) + { + break; + } + + context_p->token.type = LEXER_MULTIPLY; + lexer_consume_next_character (context_p); + return; + } + case LIT_CHAR_HASHMARK: + { + if (ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER) + { + context_p->token.type = LEXER_HASHMARK; + return; + } + + break; + } + case LIT_CHAR_LEFT_BRACE: + { + const uint32_t static_block_flags = + (LEXER_OBJ_IDENT_CLASS_NO_STATIC | LEXER_OBJ_IDENT_CLASS_PRIVATE | LEXER_OBJ_IDENT_CLASS_IDENTIFIER); + + if ((ident_opts & static_block_flags) == LEXER_OBJ_IDENT_CLASS_IDENTIFIER) + { + context_p->token.type = LEXER_LEFT_BRACE; + lexer_consume_next_character (context_p); + return; + } + + break; + } + case LIT_CHAR_RIGHT_BRACE: + { + if (ident_opts & LEXER_OBJ_IDENT_ONLY_IDENTIFIERS) + { + break; + } + + context_p->token.type = LEXER_RIGHT_BRACE; + lexer_consume_next_character (context_p); + return; + } + case LIT_CHAR_DOT: + { + if (!(context_p->source_p + 1 >= context_p->source_end_p || lit_char_is_decimal_digit (context_p->source_p[1]))) + { + if ((ident_opts & ((uint32_t) ~(LEXER_OBJ_IDENT_OBJECT_PATTERN | LEXER_OBJ_IDENT_SET_FUNCTION_START))) + || context_p->source_p + 2 >= context_p->source_end_p || context_p->source_p[1] != LIT_CHAR_DOT + || context_p->source_p[2] != LIT_CHAR_DOT) + { + break; + } + + context_p->token.type = LEXER_THREE_DOTS; + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + PARSER_PLUS_EQUAL_LC (context_p->column, 3); + context_p->source_p += 3; + return; + } + /* FALLTHRU */ + } + default: + { + const uint8_t *char_p = context_p->source_p; + + if (char_p[0] == LIT_CHAR_DOT) + { + char_p++; + } + + if (char_p < context_p->source_end_p && char_p[0] >= LIT_CHAR_0 && char_p[0] <= LIT_CHAR_9) + { + lexer_parse_number (context_p); + + if (!(ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER)) + { + lexer_construct_number_object (context_p, false, false); + } + return; + } + break; + } + } + } + + if (create_literal_object) + { + if (ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER) + { + return; + } + + if (ident_opts & LEXER_OBJ_IDENT_CLASS_PRIVATE) + { + parser_resolve_private_identifier (context_p); + return; + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return; + } + + parser_raise_error (context_p, PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED); +} /* lexer_expect_object_literal_id */ + +/** + * Read next token without checking keywords + * + * @return true if the next literal is identifier, false otherwise + */ +bool +lexer_scan_identifier (parser_context_t *context_p, /**< context */ + lexer_parse_options_t opts) /**< identifier parse options */ +{ + lexer_skip_spaces (context_p); + context_p->token.keyword_type = LEXER_EOS; + context_p->token.line = context_p->line; + context_p->token.column = context_p->column; + + if (context_p->source_p < context_p->source_end_p && lexer_parse_identifier (context_p, opts)) + { + return true; + } + + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + return false; +} /* lexer_scan_identifier */ + +/** + * Check whether the identifier is a modifier in a property definition. + */ +void +lexer_check_property_modifier (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (!(context_p->token.flags & LEXER_NO_SKIP_SPACES)); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_skip_spaces (context_p); + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + + if (context_p->source_p >= context_p->source_end_p || context_p->source_p[0] == LIT_CHAR_COMMA + || context_p->source_p[0] == LIT_CHAR_RIGHT_BRACE || context_p->source_p[0] == LIT_CHAR_LEFT_PAREN + || context_p->source_p[0] == LIT_CHAR_EQUALS || context_p->source_p[0] == LIT_CHAR_COLON) + { + return; + } + + if (lexer_compare_literal_to_string (context_p, "get", 3)) + { + context_p->token.type = LEXER_PROPERTY_GETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "set", 3)) + { + context_p->token.type = LEXER_PROPERTY_SETTER; + return; + } + + if (lexer_compare_literal_to_string (context_p, "async", 5)) + { + context_p->token.type = LEXER_KEYW_ASYNC; + return; + } +} /* lexer_check_property_modifier */ + +/** + * Compares two identifiers. + * + * Note: + * Escape sequences are allowed in the left identifier, but not in the right + * + * @return true if the two identifiers are the same + */ +static bool +lexer_compare_identifier_to_chars (const uint8_t *left_p, /**< left identifier */ + const uint8_t *right_p, /**< right identifier string */ + size_t size) /**< byte size of the two identifiers */ +{ + uint8_t utf8_buf[6]; + + do + { + if (*left_p == *right_p) + { + left_p++; + right_p++; + size--; + continue; + } + + size_t escape_size; + + if (*left_p == LIT_CHAR_BACKSLASH) + { + left_p += 2; + lit_code_point_t code_point = lexer_unchecked_hex_to_character (&left_p); + + escape_size = lit_code_point_to_cesu8_bytes (utf8_buf, code_point); + } + else if (*left_p >= LIT_UTF8_4_BYTE_MARKER) + { + lit_four_byte_utf8_char_to_cesu8 (utf8_buf, left_p); + escape_size = 3 * 2; + left_p += 4; + } + else + { + return false; + } + + size -= escape_size; + + uint8_t *utf8_p = utf8_buf; + do + { + if (*right_p++ != *utf8_p++) + { + return false; + } + } while (--escape_size > 0); + } while (size > 0); + + return true; +} /* lexer_compare_identifier_to_chars */ + +/** + * Compares an identifier to a string. + * + * Note: + * Escape sequences are allowed in the left identifier, but not in the right + * + * @return true if the identifier equals to string + */ +bool +lexer_compare_identifier_to_string (const lexer_lit_location_t *left_p, /**< left literal */ + const uint8_t *right_p, /**< right identifier string */ + size_t size) /**< byte size of the right identifier */ +{ + if (left_p->length != size) + { + return false; + } + + if (!(left_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return memcmp (left_p->char_p, right_p, size) == 0; + } + + return lexer_compare_identifier_to_chars (left_p->char_p, right_p, size); +} /* lexer_compare_identifier_to_string */ + +/** + * Compares two identifiers. + * + * Note: + * Escape sequences are allowed in both identifiers + * + * @return true if the two identifiers are the same + */ +bool +lexer_compare_identifiers (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *left_p, /**< left literal */ + const lexer_lit_location_t *right_p) /**< right literal */ +{ + prop_length_t length = left_p->length; + + if (length != right_p->length) + { + return false; + } + + if (!(left_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return lexer_compare_identifier_to_chars (right_p->char_p, left_p->char_p, length); + } + + if (!(right_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return lexer_compare_identifier_to_chars (left_p->char_p, right_p->char_p, length); + } + + if (length <= 64) + { + uint8_t buf_p[64]; + lexer_convert_ident_to_cesu8 (buf_p, left_p->char_p, length); + return lexer_compare_identifier_to_chars (right_p->char_p, buf_p, length); + } + + uint8_t *dynamic_buf_p = (uint8_t*) parser_malloc (context_p, length); + + lexer_convert_ident_to_cesu8 (dynamic_buf_p, left_p->char_p, length); + bool result = lexer_compare_identifier_to_chars (right_p->char_p, dynamic_buf_p, length); + parser_free (dynamic_buf_p, length); + + return result; +} /* lexer_compare_identifiers */ + +/** + * Compares the current identifier in the context to the parameter identifier + * + * Note: + * Escape sequences are allowed. + * + * @return true if the input identifiers are the same + */ +bool +lexer_current_is_literal (parser_context_t *context_p, /**< context */ + const lexer_lit_location_t *right_ident_p) /**< identifier */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_lit_location_t *left_ident_p = &context_p->token.lit_location; + + JERRY_ASSERT (left_ident_p->length > 0 && right_ident_p->length > 0); + + if (left_ident_p->length != right_ident_p->length) + { + return false; + } + + if (!((left_ident_p->status_flags | right_ident_p->status_flags) & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + return memcmp (left_ident_p->char_p, right_ident_p->char_p, left_ident_p->length) == 0; + } + + return lexer_compare_identifiers (context_p, left_ident_p, right_ident_p); +} /* lexer_current_is_literal */ + +/** + * Compares the current string token to "use strict". + * + * Note: + * Escape sequences are not allowed. + * + * @return true if "use strict" is found, false otherwise + */ +bool +lexer_string_is_use_strict (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL); + + return (context_p->token.lit_location.length == 10 + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + && memcmp (context_p->token.lit_location.char_p, "use strict", 10) == 0); +} /* lexer_string_is_use_strict */ + +/** + * Checks whether the string before the current token is a directive or a string literal. + * + * @return true if the string is a directive, false otherwise + */ +bool +lexer_string_is_directive (parser_context_t *context_p) /**< context */ +{ + return (context_p->token.type == LEXER_SEMICOLON || context_p->token.type == LEXER_RIGHT_BRACE + || context_p->token.type == LEXER_EOS + || ((context_p->token.flags & LEXER_WAS_NEWLINE) && !LEXER_IS_BINARY_OP_TOKEN (context_p->token.type) + && context_p->token.type != LEXER_LEFT_PAREN && context_p->token.type != LEXER_LEFT_SQUARE + && context_p->token.type != LEXER_DOT)); +} /* lexer_string_is_directive */ + +/** + * Compares the current token to an expected identifier. + * + * Note: + * Escape sequences are not allowed. + * + * @return true if they are the same, false otherwise + */ +bool +lexer_token_is_identifier (parser_context_t *context_p, /**< context */ + const char *identifier_p, /**< identifier */ + size_t identifier_length) /**< identifier length */ +{ + /* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */ + return (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL + && context_p->token.lit_location.length == identifier_length + && memcmp (context_p->token.lit_location.char_p, identifier_p, identifier_length) == 0); +} /* lexer_token_is_identifier */ + +/** + * Compares the current identifier token to "let". + * + * Note: + * Escape sequences are not allowed. + * + * @return true if "let" is found, false otherwise + */ +bool +lexer_token_is_let (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL); + + return (context_p->token.keyword_type == LEXER_KEYW_LET + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)); +} /* lexer_token_is_let */ + +/** + * Compares the current identifier token to "async". + * + * Note: + * Escape sequences are not allowed. + * + * @return true if "async" is found, false otherwise + */ +bool +lexer_token_is_async (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL || context_p->token.type == LEXER_TEMPLATE_LITERAL); + + return (context_p->token.keyword_type == LEXER_KEYW_ASYNC + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)); +} /* lexer_token_is_async */ + +/** + * Compares the current identifier or string to an expected string. + * + * Note: + * Escape sequences are not allowed. + * + * @return true if they are the same, false otherwise + */ +bool +lexer_compare_literal_to_string (parser_context_t *context_p, /**< context */ + const char *string_p, /**< string */ + size_t string_length) /**< string length */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_STRING_LITERAL)); + + /* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */ + return (context_p->token.lit_location.length == string_length + && memcmp (context_p->token.lit_location.char_p, string_p, string_length) == 0); +} /* lexer_compare_literal_to_string */ + +/** + * Initialize line info to its default value + */ +void +lexer_init_line_info (parser_context_t *context_p) /**< context */ +{ + context_p->line = 1; + context_p->column = 1; + + const jerry_parse_options_t *options_p = context_p->options_p; + + if (options_p != NULL && (options_p->options & JERRY_PARSE_HAS_START)) + { + if (options_p->start_line > 0) + { + context_p->line = options_p->start_line; + } + + if (options_p->start_column > 0) + { + context_p->column = options_p->start_column; + } + } +} /* lexer_init_line_info */ + +/** + * Convert binary lvalue token to binary token + * e.g. += -> + + * ^= -> ^ + * + * @return binary token + */ +uint8_t +lexer_convert_binary_lvalue_token_to_binary (uint8_t token) /**< binary lvalue token */ +{ + JERRY_ASSERT (LEXER_IS_BINARY_LVALUE_OP_TOKEN (token)); + JERRY_ASSERT (token != LEXER_ASSIGN); + + if (token <= LEXER_ASSIGN_EXPONENTIATION) + { + return (uint8_t) (LEXER_ADD + (token - LEXER_ASSIGN_ADD)); + } + + if (token <= LEXER_ASSIGN_UNS_RIGHT_SHIFT) + { + return (uint8_t) (LEXER_LEFT_SHIFT + (token - LEXER_ASSIGN_LEFT_SHIFT)); + } + + switch (token) + { + case LEXER_ASSIGN_BIT_AND: + { + return LEXER_BIT_AND; + } + case LEXER_ASSIGN_BIT_OR: + { + return LEXER_BIT_OR; + } + default: + { + JERRY_ASSERT (token == LEXER_ASSIGN_BIT_XOR); + return LEXER_BIT_XOR; + } + } +} /* lexer_convert_binary_lvalue_token_to_binary */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.h new file mode 100644 index 00000000..97e25d3d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-lexer.h @@ -0,0 +1,357 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_LEXER_H +#define JS_LEXER_H + +#include "ecma-globals.h" + +#include "common.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_lexer Lexer + * @{ + */ + +/** + * Flags for lexer_parse_identifier. + */ +typedef enum +{ + LEXER_PARSE_NO_OPTS = 0, /**< no options */ + LEXER_PARSE_CHECK_KEYWORDS = (1 << 0), /**< check keywords */ + LEXER_PARSE_NO_STRICT_IDENT_ERROR = (1 << 1), /**< do not throw exception for strict mode keywords */ + LEXER_PARSE_CHECK_START_AND_RETURN = (1 << 2), /**< check identifier start and return */ + LEXER_PARSE_CHECK_PART_AND_RETURN = (1 << 3), /**< check identifier part and return */ +} lexer_parse_options_t; + +/** + * Lexer token types. + */ +typedef enum +{ + LEXER_EOS, /**< end of source */ + + /* Primary expressions */ + LEXER_LITERAL, /**< literal token */ + LEXER_KEYW_THIS, /**< this */ + LEXER_LIT_TRUE, /**< true (not a keyword!) */ + LEXER_LIT_FALSE, /**< false (not a keyword!) */ + LEXER_LIT_NULL, /**< null (not a keyword!) */ + LEXER_TEMPLATE_LITERAL, /**< multi segment template literal */ + LEXER_THREE_DOTS, /**< ... (rest or spread operator) */ + +/* Unary operators + * IMPORTANT: update CBC_UNARY_OP_TOKEN_TO_OPCODE and + * CBC_UNARY_LVALUE_OP_TOKEN_TO_OPCODE after changes. */ +#define LEXER_IS_UNARY_OP_TOKEN(token_type) ((token_type) >= LEXER_PLUS && (token_type) <= LEXER_DECREASE) +#define LEXER_IS_UNARY_LVALUE_OP_TOKEN(token_type) ((token_type) >= LEXER_KEYW_DELETE && (token_type) <= LEXER_DECREASE) + + LEXER_PLUS, /**< "+" */ + LEXER_NEGATE, /**< "-" */ + LEXER_LOGICAL_NOT, /**< "!" */ + LEXER_BIT_NOT, /**< "~" */ + LEXER_KEYW_VOID, /**< void */ + LEXER_KEYW_TYPEOF, /**< typeof */ + LEXER_KEYW_AWAIT, /**< await */ + LEXER_KEYW_DELETE, /**< delete */ + LEXER_INCREASE, /**< "++" */ + LEXER_DECREASE, /**< "--" */ + +/* Binary operators + * IMPORTANT: update CBC_BINARY_OP_TOKEN_TO_OPCODE, + * CBC_BINARY_LVALUE_OP_TOKEN_TO_OPCODE and + * parser_binary_precedence_table after changes. */ +/** + * Index of first binary operation opcode. + */ +#define LEXER_FIRST_BINARY_OP LEXER_ASSIGN + +/** + * Index of last binary operation opcode. + */ +#define LEXER_LAST_BINARY_OP LEXER_EXPONENTIATION + +/** + * Checks whether the token is a binary operation token. + */ +#define LEXER_IS_BINARY_OP_TOKEN(token_type) \ + ((token_type) >= LEXER_FIRST_BINARY_OP && (token_type) <= LEXER_LAST_BINARY_OP) +/** + * Checks whether the token is an lvalue (assignment) operation token. + */ +#define LEXER_IS_BINARY_LVALUE_OP_TOKEN(token_type) \ + ((token_type) >= LEXER_ASSIGN && (token_type) <= LEXER_ASSIGN_BIT_XOR) +/** + * Checks whether the token is a non-lvalue (assignment) operation token. + */ +#define LEXER_IS_BINARY_NON_LVALUE_OP_TOKEN(token_type) \ + ((token_type) >= LEXER_QUESTION_MARK && (token_type) <= LEXER_LAST_BINARY_OP) + + LEXER_ASSIGN, /**< "=" (prec: 3) */ + LEXER_ASSIGN_ADD, /**< "+=" (prec: 3) */ + LEXER_ASSIGN_SUBTRACT, /**< "-=" (prec: 3) */ + LEXER_ASSIGN_MULTIPLY, /**< "*=" (prec: 3) */ + LEXER_ASSIGN_DIVIDE, /**< "/=" (prec: 3) */ + LEXER_ASSIGN_MODULO, /**< "%=" (prec: 3) */ + LEXER_ASSIGN_EXPONENTIATION, /**< "**=" (prec: 3) */ + LEXER_ASSIGN_NULLISH_COALESCING, /**< "??=" (prec: 3) */ + LEXER_ASSIGN_LOGICAL_OR, /**< "||=" (prec: 3) */ + LEXER_ASSIGN_LOGICAL_AND, /**< "&&=" (prec: 3) */ + LEXER_ASSIGN_LEFT_SHIFT, /**< "<<=" (prec: 3) */ + LEXER_ASSIGN_RIGHT_SHIFT, /**< ">>=" (prec: 3) */ + LEXER_ASSIGN_UNS_RIGHT_SHIFT, /**< ">>>=" (prec: 3) */ + LEXER_ASSIGN_BIT_AND, /**< "&=" (prec: 3) */ + LEXER_ASSIGN_BIT_OR, /**< "|=" (prec: 3) */ + LEXER_ASSIGN_BIT_XOR, /**< "^=" (prec: 3) */ + LEXER_QUESTION_MARK, /**< "?" (prec: 4) */ + LEXER_NULLISH_COALESCING, /**< "??" (prec: 5) */ + LEXER_LOGICAL_OR, /**< "||" (prec: 6) */ + LEXER_LOGICAL_AND, /**< "&&" (prec: 7) */ + LEXER_BIT_OR, /**< "|" (prec: 8) */ + LEXER_BIT_XOR, /**< "^" (prec: 9) */ + LEXER_BIT_AND, /**< "&" (prec: 10) */ + LEXER_EQUAL, /**< "==" (prec: 11) */ + LEXER_NOT_EQUAL, /**< "!=" (prec: 11) */ + LEXER_STRICT_EQUAL, /**< "===" (prec: 11) */ + LEXER_STRICT_NOT_EQUAL, /**< "!==" (prec: 11) */ + LEXER_LESS, /**< "<" (prec: 12) */ + LEXER_GREATER, /**< ">" (prec: 12) */ + LEXER_LESS_EQUAL, /**< "<=" (prec: 12) */ + LEXER_GREATER_EQUAL, /**< ">=" (prec: 12) */ + LEXER_KEYW_IN, /**< in (prec: 12) */ + LEXER_KEYW_INSTANCEOF, /**< instanceof (prec: 12) */ + LEXER_LEFT_SHIFT, /**< "<<" (prec: 13) */ + LEXER_RIGHT_SHIFT, /**< ">>" (prec: 13) */ + LEXER_UNS_RIGHT_SHIFT, /**< ">>>" (prec: 13) */ + LEXER_ADD, /**< "+" (prec: 14) */ + LEXER_SUBTRACT, /**< "-" (prec: 14) */ + LEXER_MULTIPLY, /**< "*" (prec: 15) */ + LEXER_DIVIDE, /**< "/" (prec: 15) */ + LEXER_MODULO, /**< "%" (prec: 15) */ + LEXER_EXPONENTIATION, /**< "**" (prec: 16) */ + LEXER_LEFT_BRACE, /**< "{" */ + LEXER_LEFT_PAREN, /**< "(" */ + LEXER_LEFT_SQUARE, /**< "[" */ + LEXER_RIGHT_BRACE, /**< "}" */ + LEXER_RIGHT_PAREN, /**< ")" */ + LEXER_RIGHT_SQUARE, /**< "]" */ + LEXER_DOT, /**< "." */ + LEXER_SEMICOLON, /**< ";" */ + LEXER_COLON, /**< ":" */ + LEXER_COMMA, /**< "," */ + LEXER_ARROW, /**< "=>" */ + LEXER_HASHMARK, /**< "#" */ + + LEXER_KEYW_BREAK, /**< break */ + LEXER_KEYW_DO, /**< do */ + LEXER_KEYW_CASE, /**< case */ + LEXER_KEYW_ELSE, /**< else */ + LEXER_KEYW_NEW, /**< new */ + LEXER_KEYW_VAR, /**< var */ + LEXER_KEYW_CATCH, /**< catch */ + LEXER_KEYW_FINALLY, /**< finally */ + LEXER_KEYW_RETURN, /**< return */ + LEXER_KEYW_CONTINUE, /**< continue */ + LEXER_KEYW_FOR, /**< for */ + LEXER_KEYW_SWITCH, /**< switch */ + LEXER_KEYW_WHILE, /**< while */ + LEXER_KEYW_DEBUGGER, /**< debugger */ + LEXER_KEYW_FUNCTION, /**< function */ + LEXER_KEYW_WITH, /**< with */ + LEXER_KEYW_DEFAULT, /**< default */ + LEXER_KEYW_IF, /**< if */ + LEXER_KEYW_THROW, /**< throw */ + LEXER_KEYW_TRY, /**< try */ + + LEXER_KEYW_CLASS, /**< class */ + LEXER_KEYW_EXTENDS, /**< extends */ + LEXER_KEYW_SUPER, /**< super */ + LEXER_KEYW_CONST, /**< const */ + LEXER_KEYW_EXPORT, /**< export */ + LEXER_KEYW_IMPORT, /**< import */ + LEXER_KEYW_ENUM, /**< enum */ + +#define LEXER_FIRST_NON_RESERVED_KEYWORD LEXER_EXPRESSION_START + + /* These are virtual tokens. */ + LEXER_EXPRESSION_START, /**< expression start */ + LEXER_PROPERTY_GETTER, /**< property getter function */ + LEXER_PROPERTY_SETTER, /**< property setter function */ + LEXER_COMMA_SEP_LIST, /**< comma separated bracketed expression list */ + LEXER_ASSIGN_GROUP_EXPR, /**< indetifier for the assignment is located in a group expression */ + LEXER_ASSIGN_CONST, /**< a const binding is reassigned */ + LEXER_INVALID_PATTERN, /**< special value for invalid destructuring pattern */ + LEXER_PRIVATE_PRIMARY_EXPR, /**< private field in primary expession position */ + LEXER_ASSIGN_REFERENCE, /**< special value for reference assignment */ + + /* Keywords which are not keyword tokens. */ + LEXER_KEYW_ASYNC, /**< async */ +#if JERRY_MODULE_SYSTEM + LEXER_KEYW_META, /**< meta */ +#endif /* JERRY_MODULE_SYSTEM */ + +/* Keywords which cannot be assigned in strict mode. */ +#define LEXER_FIRST_NON_STRICT_ARGUMENTS LEXER_KEYW_EVAL + LEXER_KEYW_EVAL, /**< eval */ + LEXER_KEYW_ARGUMENTS, /**< arguments */ + +/* Future strict reserved words: these keywords + * must form a group after non-reserved keywords. */ +#define LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD LEXER_KEYW_IMPLEMENTS + LEXER_KEYW_IMPLEMENTS, /**< implements */ + LEXER_KEYW_PRIVATE, /**< private */ + LEXER_KEYW_PUBLIC, /**< public */ + LEXER_KEYW_INTERFACE, /**< interface */ + LEXER_KEYW_PACKAGE, /**< package */ + LEXER_KEYW_PROTECTED, /**< protected */ + + /* Context dependent future strict reserved words: + * See also: ECMA-262 v6, 11.6.2.1 */ + LEXER_KEYW_LET, /**< let */ + LEXER_KEYW_YIELD, /**< yield */ + LEXER_KEYW_STATIC, /**< static */ +} lexer_token_type_t; + +#define LEXER_NEWLINE_LS_PS_BYTE_1 0xe2 +#define LEXER_NEWLINE_LS_PS_BYTE_23(source) \ + ((source)[1] == LIT_UTF8_2_BYTE_CODE_POINT_MIN && ((source)[2] | 0x1) == 0xa9) + +#define LEXER_IS_LEFT_BRACKET(type) \ + ((type) == LEXER_LEFT_BRACE || (type) == LEXER_LEFT_PAREN || (type) == LEXER_LEFT_SQUARE) + +#define LEXER_IS_RIGHT_BRACKET(type) \ + ((type) == LEXER_RIGHT_BRACE || (type) == LEXER_RIGHT_PAREN || (type) == LEXER_RIGHT_SQUARE) + +#define LEXER_UNARY_OP_TOKEN_TO_OPCODE(token_type) ((((token_type) -LEXER_PLUS) * 2) + CBC_PLUS) + +#define LEXER_UNARY_LVALUE_OP_TOKEN_TO_OPCODE(token_type) ((((token_type) -LEXER_INCREASE) * 6) + CBC_PRE_INCR) + +#define LEXER_BINARY_OP_TOKEN_TO_OPCODE(token_type) ((uint16_t) ((((token_type) -LEXER_BIT_OR) * 3) + CBC_BIT_OR)) + +#define LEXER_BINARY_LVALUE_OP_TOKEN_TO_OPCODE(token_type) \ + ((cbc_opcode_t) ((((token_type) -LEXER_ASSIGN_ADD) * 2) + CBC_ASSIGN_ADD)) + +/** + * Maximum local buffer size for identifiers which contains escape sequences. + */ +#define LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE 48 + +/** + * Lexer newline flags. + */ +typedef enum +{ + LEXER_WAS_NEWLINE = (1u << 0), /**< newline was seen */ + LEXER_NO_SKIP_SPACES = (1u << 1) /**< ignore skip spaces */ +} lexer_newline_flags_t; + +/** + * Lexer object identifier parse options. + */ +typedef enum +{ + LEXER_OBJ_IDENT_NO_OPTS = 0, /**< no options */ + LEXER_OBJ_IDENT_ONLY_IDENTIFIERS = (1u << 0), /**< only identifiers are accepted */ + LEXER_OBJ_IDENT_CLASS_IDENTIFIER = (1u << 1), /**< expect identifier inside a class body */ + LEXER_OBJ_IDENT_CLASS_NO_STATIC = (1u << 2), /**< static keyword was not present before the identifier */ + LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 3), /**< parse "get"/"set" as string literal in object pattern */ + LEXER_OBJ_IDENT_CLASS_PRIVATE = (1u << 4), /**< static keyword was not present before the identifier */ +#if JERRY_FUNCTION_TO_STRING + LEXER_OBJ_IDENT_SET_FUNCTION_START = (1u << 5), /**< set function start */ +#else /* !JERRY_FUNCTION_TO_STRING */ + LEXER_OBJ_IDENT_SET_FUNCTION_START = 0, /**< set function start (disabled) */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} lexer_obj_ident_opts_t; + +/** + * Lexer string options. + */ +typedef enum +{ + LEXER_STRING_NO_OPTS = (1u << 0), /**< no options */ + LEXER_STRING_RAW = (1u << 1), /**< raw string ECMAScript v6, 11.8.6.1: TVR */ +} lexer_string_options_t; + +/** + * Lexer number types. + */ +typedef enum +{ + LEXER_NUMBER_DECIMAL, /**< decimal number */ + LEXER_NUMBER_HEXADECIMAL, /**< hexadecimal number */ + LEXER_NUMBER_OCTAL, /**< octal number */ + LEXER_NUMBER_BINARY, /**< binary number */ +#if JERRY_BUILTIN_BIGINT + LEXER_NUMBER_BIGINT, /**< bigint number */ +#endif /* JERRY_BUILTIN_BIGINT */ +} lexer_number_type_t; + +/** + * Lexer literal flags. + **/ +typedef enum +{ + LEXER_LIT_LOCATION_NO_OPTS = 0, /**< no options */ + LEXER_LIT_LOCATION_HAS_ESCAPE = (1 << 0), /**< binding has escape */ + LEXER_LIT_LOCATION_IS_ASCII = (1 << 1), /**< all characters are ascii characters */ +} lexer_lit_location_flags_t; + +/** + * Lexer character (string / identifier) literal data. + */ +typedef struct +{ + const uint8_t *char_p; /**< start of identifier or string token */ + prop_length_t length; /**< length or index of a literal */ + uint8_t type; /**< type of the current literal */ + uint8_t status_flags; /**< any combination of lexer_lit_location_flags_t status bits */ +} lexer_lit_location_t; + +/** + * Lexer token. + */ +typedef struct +{ + uint8_t type; /**< token type */ + uint8_t keyword_type; /**< keyword type for identifiers */ + uint8_t extra_value; /**< helper value for different purposes */ + uint8_t flags; /**< flag bits for the current token */ + parser_line_counter_t line; /**< token start line */ + parser_line_counter_t column; /**< token start column */ + lexer_lit_location_t lit_location; /**< extra data for character literals */ +} lexer_token_t; + +/** + * Literal data set by lexer_construct_literal_object. + */ +typedef struct +{ + lexer_literal_t *literal_p; /**< pointer to the literal object */ + uint16_t index; /**< literal index */ +} lexer_lit_object_t; + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_LEXER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-expr.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-expr.cpp new file mode 100644 index 00000000..f30568a4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-expr.cpp @@ -0,0 +1,4182 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_PARSER +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "js-parser-tagged-template-literal.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_expr Expression parser + * @{ + */ + +/** + * Maximum precedence for right-to-left binary operation evaluation. + */ +#define PARSER_RIGHT_TO_LEFT_ORDER_MAX_PRECEDENCE 7 + +/** + * Precedence for ternary operation. + */ +#define PARSER_RIGHT_TO_LEFT_ORDER_TERNARY_PRECEDENCE 4 + +/** + * Precedence for exponentiation operation. + */ +#define PARSER_RIGHT_TO_LEFT_ORDER_EXPONENTIATION 16 + +/** + * Value of grouping level increase and decrease. + */ +#define PARSER_GROUPING_LEVEL_INCREASE 2 + +/** + * Precedence of the binary tokens. + * + * See also: + * lexer_token_type_t + */ +static const uint8_t parser_binary_precedence_table[] = { + 3, /**< "=" */ + 3, /**< "+=" */ + 3, /**< "-=" */ + 3, /**< "*=" */ + 3, /**< "/=" */ + 3, /**< "=" */ + 3, /**< "<<=" */ + 3, /**< ">>=" */ + 3, /**< ">>>=" */ + 3, /**< "&=" */ + 3, /**< "|=" */ + 3, /**< "^=" */ + 3, /**< "**=" */ + 3, /**< "??=" */ + 3, /**< "||=" */ + 3, /**< "&&=" */ + 4, /**< "?"*/ + 5, /**< "??" */ + 6, /**< "||" */ + 7, /**< "&&" */ + 8, /**< "|" */ + 9, /**< "^" */ + 10, /**< "&" */ + 11, /**< "==" */ + 11, /**< "!=" */ + 11, /**< "===" */ + 11, /**< "!==" */ + 12, /**< "<" */ + 12, /**< ">" */ + 12, /**< "<=" */ + 12, /**< ">=" */ + 12, /**< in */ + 12, /**< instanceof */ + 13, /**< "<<" */ + 13, /**< ">>" */ + 13, /**< ">>>" */ + 14, /**< "+" */ + 14, /**< "-" */ + 15, /**< "*" */ + 15, /**< "/" */ + 15, /**< "%" */ + 16, /**< "**" */ +}; + +JERRY_STATIC_ASSERT ((sizeof (parser_binary_precedence_table) == 42), + parser_binary_precedence_table_should_have_39_values_in_es2015); + +/** + * Generate byte code for operators with lvalue. + */ +static inline void +parser_push_result (parser_context_t *context_p) /**< context */ +{ + if (CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, context_p->last_cbc_opcode + 1)); + + if ((context_p->last_cbc_opcode == CBC_POST_INCR || context_p->last_cbc_opcode == CBC_POST_DECR) + && context_p->stack_depth >= context_p->stack_limit) + { + /* Stack limit is increased for CBC_POST_INCR_PUSH_RESULT + * and CBC_POST_DECR_PUSH_RESULT opcodes. Needed by vm.c. */ + JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit); + + context_p->stack_limit++; + + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } + + context_p->last_cbc_opcode++; + parser_flush_cbc (context_p); + } +} /* parser_push_result */ + +/** + * Check for invalid assignment for "eval" and "arguments" + */ +static void +parser_check_invalid_assign (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL); + + if (JERRY_UNLIKELY (context_p->status_flags & PARSER_IS_STRICT)) + { + if (context_p->last_cbc.literal_keyword_type == LEXER_KEYW_EVAL) + { + parser_raise_error (context_p, PARSER_ERR_EVAL_CANNOT_ASSIGNED); + } + else if (context_p->last_cbc.literal_keyword_type == LEXER_KEYW_ARGUMENTS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_CANNOT_ASSIGNED); + } + } +} /* parser_check_invalid_assign */ + +/** + * Check and throw an error if the "new.target" is invalid as a left-hand side expression. + */ +static void +parser_check_invalid_new_target (parser_context_t *context_p, /**< parser context */ + cbc_opcode_t opcode) /**< current opcode under parsing */ +{ + /* new.target is an invalid left-hand side target */ + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_NEW_TARGET)) + { + /* Make sure that the call side is a post/pre increment or an assignment expression. + * There should be no other ways the "new.target" expression should be here. */ + JERRY_ASSERT ( + (opcode >= CBC_PRE_INCR && opcode <= CBC_POST_DECR) + || (opcode == CBC_ASSIGN + && (context_p->token.type == LEXER_ASSIGN || LEXER_IS_BINARY_LVALUE_OP_TOKEN (context_p->token.type)))); + + parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_NOT_ALLOWED); + } +} /* parser_check_invalid_new_target */ + +/** + * Emit identifier reference + */ +static void +parser_emit_ident_reference (parser_context_t *context_p, /**< context */ + uint16_t opcode) /* opcode */ +{ + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = opcode; + return; + } + + uint16_t literal_index; + + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + literal_index = context_p->last_cbc.value; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THIS_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_THIS; + literal_index = context_p->last_cbc.literal_index; + } + else + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS); + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + literal_index = context_p->last_cbc.third_literal_index; + } + + parser_emit_cbc_literal (context_p, opcode, literal_index); +} /* parser_emit_ident_reference */ + +/** + * Generate byte code for operators with lvalue. + */ +static void +parser_emit_unary_lvalue_opcode (parser_context_t *context_p, /**< context */ + cbc_opcode_t opcode) /**< opcode */ +{ + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_check_invalid_assign (context_p); + + uint16_t unary_opcode; + + if (opcode == CBC_DELETE_PUSH_RESULT) + { + if (JERRY_UNLIKELY (context_p->status_flags & PARSER_IS_STRICT)) + { + parser_raise_error (context_p, PARSER_ERR_DELETE_IDENT_NOT_ALLOWED); + } + + unary_opcode = CBC_DELETE_IDENT_PUSH_RESULT; + } + else + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, opcode + CBC_UNARY_LVALUE_WITH_IDENT)); + unary_opcode = (uint16_t) (opcode + CBC_UNARY_LVALUE_WITH_IDENT); + } + + parser_emit_ident_reference (context_p, unary_opcode); + + if (unary_opcode != CBC_DELETE_IDENT_PUSH_RESULT + && scanner_literal_is_const_reg (context_p, context_p->last_cbc.literal_index)) + { + /* The current value must be read, but it cannot be changed. */ + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + parser_emit_cbc_ext (context_p, CBC_EXT_THROW_ASSIGN_CONST_ERROR); + } + return; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_PROP) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, opcode)); + context_p->last_cbc_opcode = (uint16_t) opcode; + return; + } + + if (PARSER_IS_PUSH_PROP_LITERAL (context_p->last_cbc_opcode)) + { + context_p->last_cbc_opcode = PARSER_PUSH_PROP_LITERAL_TO_PUSH_LITERAL (context_p->last_cbc_opcode); + } + else + { + /* Invalid LeftHandSide expression. */ + if (opcode == CBC_DELETE_PUSH_RESULT) + { + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL)) + { + parser_raise_error (context_p, PARSER_ERR_DELETE_PRIVATE_FIELD); + } + + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL) + || context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR); + parser_emit_cbc (context_p, CBC_POP); + return; + } + + parser_emit_cbc (context_p, CBC_POP); + parser_emit_cbc (context_p, CBC_PUSH_TRUE); + return; + } + + parser_check_invalid_new_target (context_p, opcode); + if (opcode == CBC_PRE_INCR || opcode == CBC_PRE_DECR) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_PREFIX_OP); + } + else + { + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_POSTFIX_OP); + } + } + + parser_emit_cbc (context_p, (uint16_t) opcode); +} /* parser_emit_unary_lvalue_opcode */ + +/** + * Parse array literal. + */ +static void +parser_parse_array_literal (parser_context_t *context_p) /**< context */ +{ + uint32_t pushed_items = 0; + uint16_t opcode = (uint16_t) CBC_ARRAY_APPEND; + + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_SQUARE); + + parser_emit_cbc (context_p, CBC_CREATE_ARRAY); + lexer_next_token (context_p); + + while (true) + { + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + if (pushed_items > 0) + { + parser_emit_cbc_call (context_p, opcode, pushed_items); + } + return; + } + + pushed_items++; + + if (context_p->token.type == LEXER_COMMA) + { + parser_emit_cbc (context_p, CBC_PUSH_ELISION); + lexer_next_token (context_p); + } + else + { + if (context_p->token.type == LEXER_THREE_DOTS) + { + opcode = (uint16_t) (PARSER_TO_EXT_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND)); + pushed_items++; + lexer_next_token (context_p); + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SPREAD_ELEMENT); + } + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->last_cbc_opcode == CBC_PUSH_THIS) + { + parser_flush_cbc (context_p); + } + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + else if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_ARRAY_ITEM_SEPARATOR_EXPECTED); + } + } + + if (pushed_items >= 64) + { + parser_emit_cbc_call (context_p, opcode, pushed_items); + opcode = (uint16_t) CBC_ARRAY_APPEND; + pushed_items = 0; + } + } +} /* parser_parse_array_literal */ + +/** Forward definition of parse array initializer. */ +static void parser_parse_array_initializer (parser_context_t *context_p, parser_pattern_flags_t flags); + +/** Forward definition of parse object initializer. */ +static void parser_parse_object_initializer (parser_context_t *context_p, parser_pattern_flags_t flags); + +/** + * Class literal parsing options. + */ +typedef enum +{ + PARSER_CLASS_LITERAL_NO_OPTS = 0, /**< no options are provided */ + PARSER_CLASS_LITERAL_CTOR_PRESENT = (1 << 0), /**< class constructor is present */ + PARSER_CLASS_LITERAL_HERTIAGE_PRESENT = (1 << 1), /**< class heritage is present */ +} parser_class_literal_opts_t; + +/** + * Checks whether the current string or identifier literal is constructor + * + * @return true, if constructor and false otherwise + */ +static inline bool +parser_is_constructor_literal (parser_context_t *context_p) /**< context */ +{ + return (LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_literal_to_string (context_p, "constructor", 11)); +} /* parser_is_constructor_literal */ + +/** + * Checks if current private field is already declared + */ +static void +parser_check_duplicated_private_field (parser_context_t *context_p, /**< context */ + uint8_t opts) /**< options */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL); + JERRY_ASSERT (context_p->private_context_p); + scanner_class_private_member_t *iter = context_p->private_context_p->members_p; + + bool search_for_property = (opts & SCANNER_PRIVATE_FIELD_PROPERTY); + + while (iter != NULL) + { + if (lexer_compare_identifiers (context_p, &context_p->token.lit_location, &iter->loc) && (iter->u8_arg & opts)) + { + if (iter->u8_arg & SCANNER_PRIVATE_FIELD_SEEN) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_PRIVATE_FIELD); + } + + iter->u8_arg |= SCANNER_PRIVATE_FIELD_SEEN; + + if (!search_for_property) + { + break; + } + } + + iter = iter->prev_p; + } +} /* parser_check_duplicated_private_field */ + +/** + * Parse class literal. + * + * @return true - if the class has static fields, false - otherwise + */ +static bool +parser_parse_class_body (parser_context_t *context_p, /**< context */ + parser_class_literal_opts_t opts, /**< class literal parsing options */ + uint16_t class_name_index) /**< class literal index */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + + lexer_literal_t *ctor_literal_p = NULL; + lexer_literal_t *static_fields_literal_p = NULL; + + if (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT) + { + ctor_literal_p = lexer_construct_unused_literal (context_p); + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, (uint16_t) (context_p->literal_count++)); + } + else if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR); + } + + if (class_name_index != PARSER_INVALID_LITERAL_INDEX) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, class_name_index); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_INIT_CLASS); + + bool is_static = false; + bool is_private = false; + size_t fields_size = 0; + uint32_t computed_field_count = 0; + + while (true) + { + if (!is_static) + { + lexer_skip_empty_statements (context_p); + } + + uint32_t flags = (LEXER_OBJ_IDENT_CLASS_IDENTIFIER | LEXER_OBJ_IDENT_SET_FUNCTION_START); + + if (!is_static) + { + flags |= LEXER_OBJ_IDENT_CLASS_NO_STATIC; + } + + if (is_private) + { + flags |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + } + + lexer_expect_object_literal_id (context_p, flags); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + JERRY_ASSERT (!is_static); + break; + } + + if (context_p->token.type == LEXER_HASHMARK) + { + is_private = true; + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + continue; + } + + if (context_p->token.type == LEXER_KEYW_STATIC) + { + JERRY_ASSERT (!is_static); + is_static = true; + continue; + } + + bool is_constructor_literal = false; + + if (context_p->token.type == LEXER_LITERAL) + { + is_constructor_literal = parser_is_constructor_literal (context_p); + + if (is_private) + { + if (is_constructor_literal && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR); + } + + parser_check_duplicated_private_field (context_p, SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER); + } + } + + if (!is_static && is_constructor_literal) + { + JERRY_ASSERT (!is_static); + JERRY_ASSERT (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT); + JERRY_ASSERT (ctor_literal_p != NULL); + + if (ctor_literal_p->type == LEXER_FUNCTION_LITERAL) + { + /* 14.5.1 */ + parser_raise_error (context_p, PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS); + } + + uint32_t constructor_status_flags = + (PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER | PARSER_CLASS_CONSTRUCTOR | PARSER_LEXICAL_ENV_NEEDED); + + if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT) + { + constructor_status_flags |= PARSER_ALLOW_SUPER_CALL; + } + + if (context_p->status_flags & PARSER_INSIDE_WITH) + { + constructor_status_flags |= PARSER_INSIDE_WITH; + } + + parser_flush_cbc (context_p); + ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, constructor_status_flags); + ctor_literal_p->u.bytecode_p = compiled_code_p; + ctor_literal_p->type = LEXER_FUNCTION_LITERAL; + continue; + } + + bool is_computed = false; + + if (context_p->token.type == LEXER_PROPERTY_GETTER || context_p->token.type == LEXER_PROPERTY_SETTER) + { + uint16_t literal_index, function_literal_index; + bool is_getter = (context_p->token.type == LEXER_PROPERTY_GETTER); + + uint32_t accessor_status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER; + accessor_status_flags |= (is_getter ? PARSER_IS_PROPERTY_GETTER : PARSER_IS_PROPERTY_SETTER); + + uint8_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + is_private = true; + } + + lexer_expect_object_literal_id (context_p, ident_opts); + + if (is_private) + { + parser_check_duplicated_private_field (context_p, + is_getter ? SCANNER_PRIVATE_FIELD_GETTER : SCANNER_PRIVATE_FIELD_SETTER); + } + + literal_index = context_p->lit_object.index; + + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + is_computed = true; + } + else if (is_static && !is_private) + { + if (LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_identifier_to_string (&context_p->token.lit_location, (uint8_t *) "prototype", 9)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE); + } + } + else if (parser_is_constructor_literal (context_p)) + { + JERRY_ASSERT (!is_static || is_private); + parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR); + } + + function_literal_index = lexer_construct_function_object (context_p, accessor_status_flags); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, literal_index); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + cbc_ext_opcode_t opcode; + + if (is_computed) + { + context_p->last_cbc.literal_index = function_literal_index; + + if (is_getter) + { + opcode = is_static ? CBC_EXT_SET_STATIC_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_GETTER; + } + else + { + opcode = is_static ? CBC_EXT_SET_STATIC_COMPUTED_SETTER : CBC_EXT_SET_COMPUTED_SETTER; + } + } + else + { + context_p->last_cbc.value = function_literal_index; + + if (is_getter) + { + opcode = is_static ? (is_private ? CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER : CBC_EXT_SET_STATIC_GETTER) + : (is_private ? CBC_EXT_COLLECT_PRIVATE_GETTER : CBC_EXT_SET_GETTER); + } + else + { + opcode = is_static ? (is_private ? CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER : CBC_EXT_SET_STATIC_SETTER) + : (is_private ? CBC_EXT_COLLECT_PRIVATE_SETTER : CBC_EXT_SET_SETTER); + } + } + + if (is_computed) + { + parser_emit_cbc_ext (context_p, + is_getter ? CBC_EXT_SET_COMPUTED_GETTER_NAME : CBC_EXT_SET_COMPUTED_SETTER_NAME); + parser_emit_cbc_ext (context_p, opcode); + } + else + { + if (is_private) + { + accessor_status_flags |= PARSER_PRIVATE_FUNCTION_NAME; + } + parser_set_function_name (context_p, function_literal_index, literal_index, accessor_status_flags); + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode); + } + + is_static = false; + is_private = false; + continue; + } + + uint32_t status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER; + + if (context_p->token.type == LEXER_KEYW_ASYNC) + { + status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + + uint8_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + is_private = true; + } + + if (!lexer_consume_generator (context_p)) + { + lexer_expect_object_literal_id (context_p, ident_opts); + } + + if (is_private && context_p->token.type == LEXER_LITERAL) + { + if (parser_is_constructor_literal (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR); + } + + parser_check_duplicated_private_field (context_p, SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER); + } + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + uint8_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + is_private = true; + } + + lexer_expect_object_literal_id (context_p, ident_opts); + + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + + if (is_private && context_p->token.type == LEXER_LITERAL) + { + if (parser_is_constructor_literal (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR); + } + + parser_check_duplicated_private_field (context_p, SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER); + } + } + + bool is_static_block = context_p->token.type == LEXER_LEFT_BRACE; + + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + is_computed = true; + } + else if (!is_static_block && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)) + { + if (is_static && !is_private) + { + if (lexer_compare_identifier_to_string (&context_p->token.lit_location, (uint8_t *) "prototype", 9)) + { + parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE); + } + } + else if ((status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION)) + && lexer_compare_literal_to_string (context_p, "constructor", 11)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CLASS_CONSTRUCTOR); + } + } + + if (!(status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION))) + { + if (is_static_block || !lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + /* Class field. */ + if (fields_size == 0) + { + parser_stack_push_uint8 (context_p, PARSER_CLASS_FIELD_END); + } + + scanner_range_t range; + uint8_t class_field_type = is_static ? PARSER_CLASS_FIELD_STATIC : 0; + + if (!is_computed) + { + if (is_private) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + uint8_t field_opcode = is_static ? CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD : CBC_EXT_COLLECT_PRIVATE_FIELD; + parser_emit_cbc_ext_literal_from_token (context_p, field_opcode); + } + + if (is_static && !is_static_block && parser_is_constructor_literal (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIST_EXPECTED); + } + + range.start_location.source_p = context_p->token.lit_location.char_p; + range.start_location.line = context_p->token.line; + range.start_location.column = context_p->token.column; + class_field_type |= PARSER_CLASS_FIELD_NORMAL; + + if (context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + range.start_location.source_p--; + } + } + else + { + if (++computed_field_count > ECMA_INTEGER_NUMBER_MAX) + { + parser_raise_error (context_p, PARSER_ERR_TOO_MANY_CLASS_FIELDS); + } + + if (is_static && static_fields_literal_p == NULL) + { + static_fields_literal_p = lexer_construct_unused_literal (context_p); + parser_emit_cbc_ext_literal (context_p, + CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC, + (uint16_t) (context_p->literal_count++)); + } + else + { + parser_emit_cbc_ext (context_p, + (is_static ? CBC_EXT_ADD_STATIC_COMPUTED_FIELD : CBC_EXT_ADD_COMPUTED_FIELD)); + } + } + + if (is_static_block) + { + class_field_type |= PARSER_CLASS_FIELD_STATIC_BLOCK; + + if (context_p->next_scanner_info_p->type != SCANNER_TYPE_CLASS_STATIC_BLOCK_END) + { + parser_flush_cbc (context_p); + parser_parse_class_static_block (context_p); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CLASS_STATIC_BLOCK_END); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + range.start_location.source_p = context_p->next_scanner_info_p->source_p - 1; + + scanner_seek (context_p); + + parser_stack_push (context_p, &range.start_location, sizeof (scanner_location_t)); + fields_size += sizeof (scanner_location_t); + + lexer_consume_next_character (context_p); + } + else if (lexer_consume_assign (context_p)) + { + class_field_type |= PARSER_CLASS_FIELD_INITIALIZED; + + if (context_p->next_scanner_info_p->source_p != context_p->source_p) + { + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + if (is_computed) + { + scanner_get_location (&range.start_location, context_p); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END); + range.source_end_p = ((scanner_location_info_t *) context_p->next_scanner_info_p)->location.source_p; + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + + parser_stack_push (context_p, &range, sizeof (scanner_range_t)); + fields_size += sizeof (scanner_range_t); + } + else + { + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) + && !lexer_check_next_characters (context_p, LIT_CHAR_SEMICOLON, LIT_CHAR_RIGHT_BRACE)) + { + lexer_next_token (context_p); + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + if (!is_computed) + { + parser_stack_push (context_p, &range.start_location, sizeof (scanner_location_t)); + fields_size += sizeof (scanner_location_t); + } + } + + parser_stack_push_uint8 (context_p, class_field_type); + fields_size++; + is_static = false; + is_private = false; + continue; + } + + if (!is_computed) + { + if (context_p->token.lit_location.type != LEXER_NUMBER_LITERAL) + { + JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_STRING_LITERAL); + if (is_private) + { + parser_resolve_private_identifier (context_p); + } + else + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + } + } + else + { + lexer_construct_number_object (context_p, false, false); + } + } + } + + uint16_t literal_index = context_p->lit_object.index; + uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags | PARSER_IS_METHOD); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + if (is_computed) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + parser_emit_cbc_ext (context_p, is_static ? CBC_EXT_SET_STATIC_COMPUTED_PROPERTY : CBC_EXT_SET_COMPUTED_PROPERTY); + is_static = false; + continue; + } + + uint32_t function_name_status_flags = 0; + + if (is_private) + { + function_name_status_flags = PARSER_PRIVATE_FUNCTION_NAME; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, function_name_status_flags); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + context_p->last_cbc.value = literal_index; + + if (is_static) + { + context_p->last_cbc_opcode = (is_private ? PARSER_TO_EXT_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD) + : PARSER_TO_EXT_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL)); + is_static = false; + } + else if (is_private) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD); + } + else + { + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + } + + is_private = false; + } + + if (fields_size == 0) + { + return false; + } + + parser_reverse_class_fields (context_p, fields_size); + + /* Since PARSER_IS_ARROW_FUNCTION and PARSER_CLASS_CONSTRUCTOR bits cannot + * be set at the same time, this bit combination triggers class field parsing. */ + + if (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_STATIC)) + { + lexer_literal_t *literal_p = lexer_construct_unused_literal (context_p); + + uint16_t function_literal_index = (uint16_t) (context_p->literal_count++); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_FIELD_INIT, function_literal_index); + parser_flush_cbc (context_p); + + literal_p->u.bytecode_p = parser_parse_class_fields (context_p); + literal_p->type = LEXER_FUNCTION_LITERAL; + } + + bool has_static_field = false; + + if (context_p->stack_top_uint8 & PARSER_CLASS_FIELD_STATIC) + { + if (static_fields_literal_p == NULL) + { + static_fields_literal_p = lexer_construct_unused_literal (context_p); + uint16_t function_literal_index = (uint16_t) (context_p->literal_count++); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_STATIC_FIELD_FUNC, function_literal_index); + } + + parser_flush_cbc (context_p); + static_fields_literal_p->u.bytecode_p = parser_parse_class_fields (context_p); + static_fields_literal_p->type = LEXER_FUNCTION_LITERAL; + + has_static_field = true; + } + + parser_stack_pop_uint8 (context_p); + return has_static_field; +} /* parser_parse_class_body */ + +/** + * Parse class statement or expression. + */ +void +parser_parse_class (parser_context_t *context_p, /**< context */ + bool is_statement) /**< true - if class is parsed as a statement + * false - otherwise (as an expression) */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS); + + uint16_t class_ident_index = PARSER_INVALID_LITERAL_INDEX; + uint16_t class_name_index = PARSER_INVALID_LITERAL_INDEX; + parser_class_literal_opts_t opts = PARSER_CLASS_LITERAL_NO_OPTS; + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + + scanner_class_info_t *class_info_p = (scanner_class_info_t *) scanner_info_p; + parser_private_context_t private_ctx; + + if (scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR); + parser_save_private_context (context_p, &private_ctx, class_info_p); + + if (scanner_info_p->u8_arg & SCANNER_CONSTRUCTOR_EXPLICIT) + { + opts = (parser_class_literal_opts_t) ((int) opts | (int) PARSER_CLASS_LITERAL_CTOR_PRESENT); + } + + scanner_release_next (context_p, sizeof (scanner_class_info_t)); + } + + if (is_statement) + { + /* Class statement must contain an identifier. */ + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + class_ident_index = context_p->lit_object.index; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + class_name_index = context_p->lit_object.index; + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); + context_p->status_flags &= (uint32_t) ~PARSER_MODULE_STORE_IDENT; +#endif /* JERRY_MODULE_SYSTEM */ + + lexer_next_token (context_p); + } + else + { + lexer_next_token (context_p); + + /* Class expression may contain an identifier. */ + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + class_name_index = context_p->lit_object.index; + lexer_next_token (context_p); + } + } + + if (class_name_index != PARSER_INVALID_LITERAL_INDEX) + { + if (JERRY_UNLIKELY (context_p->scope_stack_top >= context_p->scope_stack_size)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + PARSER_PLUS_EQUAL_U16 (context_p->scope_stack_top, 1); + scope_stack_p->map_from = class_name_index; + scope_stack_p->map_to = 0; + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_NAMED_CLASS_ENV, class_name_index); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + } + + bool is_strict = (context_p->status_flags & PARSER_IS_STRICT) != 0; + + /* 14.5. A ClassBody is always strict code. */ + context_p->status_flags |= PARSER_IS_STRICT; + + if (context_p->token.type == LEXER_KEYW_EXTENDS) + { + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR | PARSE_EXPR_LEFT_HAND_SIDE); + opts = (parser_class_literal_opts_t) ((int) opts | (int) PARSER_CLASS_LITERAL_HERTIAGE_PRESENT); + } + else + { + /* Elisions represents that the classHeritage is not present */ + parser_emit_cbc (context_p, CBC_PUSH_ELISION); + } + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + + context_p->private_context_p->opts |= SCANNER_PRIVATE_FIELD_ACTIVE; + + /* ClassDeclaration is parsed. Continue with class body. */ + bool has_static_field = parser_parse_class_body (context_p, opts, class_name_index); + + if (class_name_index != PARSER_INVALID_LITERAL_INDEX) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_FINALIZE_NAMED_CLASS, class_name_index); + PARSER_MINUS_EQUAL_U16 (context_p->scope_stack_top, 1); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_FINALIZE_ANONYMOUS_CLASS); + } + + if (has_static_field) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RUN_STATIC_FIELD_INIT); + } + + if (is_statement) + { + cbc_opcode_t opcode = CBC_MOV_IDENT; + + if (class_ident_index < PARSER_REGISTER_START) + { + opcode = (scanner_literal_is_created (context_p, class_ident_index) ? CBC_ASSIGN_LET_CONST : CBC_INIT_LET); + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, class_ident_index); + parser_flush_cbc (context_p); + } + + if (!is_strict) + { + /* Restore flag */ + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + context_p->status_flags &= (uint32_t) ~PARSER_ALLOW_SUPER; + + parser_restore_private_context (context_p, &private_ctx); + + lexer_next_token (context_p); +} /* parser_parse_class */ + +/** + * Parse object initializer method definition. + * + * See also: ES2015 14.3 + */ +static void +parser_parse_object_method (parser_context_t *context_p) /**< context */ +{ + context_p->source_p--; + context_p->column--; + uint16_t function_literal_index = + lexer_construct_function_object (context_p, (PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER | PARSER_IS_METHOD)); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL; + + lexer_next_token (context_p); +} /* parser_parse_object_method */ + +/** + * Reparse the current literal as a common identifier. + */ +static void +parser_reparse_as_common_identifier (parser_context_t *context_p, /**< context */ + parser_line_counter_t start_line, /**< start line */ + parser_line_counter_t start_column) /**< start column */ +{ + /* context_p->token.lit_location.char_p is showing the character after the string start, + so it is not suitable for reparsing as identifier. + e.g.: { 'foo' } */ + if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + context_p->source_p = context_p->token.lit_location.char_p; + context_p->line = start_line; + context_p->column = start_column; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + +} /* parser_reparse_as_common_identifier */ + +/** + * Parse object literal. + */ +static void +parser_parse_object_literal (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + + parser_emit_cbc (context_p, CBC_CREATE_OBJECT); + + bool proto_seen = false; + bool has_super_env = false; + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_SUPER) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT); + has_super_env = true; + } + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + while (true) + { + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_SET_FUNCTION_START); + + switch (context_p->token.type) + { + case LEXER_RIGHT_BRACE: + { + break; + } + case LEXER_PROPERTY_GETTER: + case LEXER_PROPERTY_SETTER: + { + uint32_t status_flags; + cbc_ext_opcode_t opcode; + bool is_getter = context_p->token.type == LEXER_PROPERTY_GETTER; + + if (is_getter) + { + status_flags = PARSER_FUNCTION_CLOSURE | PARSER_IS_PROPERTY_GETTER; + opcode = CBC_EXT_SET_GETTER; + } + else + { + status_flags = PARSER_FUNCTION_CLOSURE | PARSER_IS_PROPERTY_SETTER; + opcode = CBC_EXT_SET_SETTER; + } + + status_flags |= PARSER_ALLOW_SUPER; + + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS); + + /* This assignment is a nop for computed getters/setters. */ + uint16_t literal_index = context_p->lit_object.index; + + bool is_computed = context_p->token.type == LEXER_RIGHT_SQUARE; + + if (is_computed) + { + opcode = ((opcode == CBC_EXT_SET_GETTER) ? CBC_EXT_SET_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_SETTER); + } + + uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags); + + if (opcode >= CBC_EXT_SET_COMPUTED_GETTER) + { + literal_index = function_literal_index; + } + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, literal_index); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + if (is_computed) + { + parser_emit_cbc_ext (context_p, + is_getter ? CBC_EXT_SET_COMPUTED_GETTER_NAME : CBC_EXT_SET_COMPUTED_SETTER_NAME); + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + } + parser_emit_cbc_ext (context_p, opcode); + lexer_next_token (context_p); + break; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, status_flags); + + if (has_super_env) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.value = function_literal_index; + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + parser_emit_cbc_ext (context_p, is_getter ? CBC_EXT_SET_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_SETTER); + } + else + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode); + context_p->last_cbc.value = function_literal_index; + } + + lexer_next_token (context_p); + break; + } + case LEXER_RIGHT_SQUARE: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + parser_parse_object_method (context_p); + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + if (parser_check_anonymous_function_declaration (context_p) < PARSER_NAMED_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + } + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_PROPERTY); + } + else + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + } + + break; + } + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (parser_check_anonymous_function_declaration (context_p) < PARSER_NAMED_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_PROPERTY); + } + break; + } + case LEXER_THREE_DOTS: + { + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_emit_cbc_ext (context_p, CBC_EXT_COPY_DATA_PROPERTIES); + break; + } + case LEXER_KEYW_ASYNC: + case LEXER_MULTIPLY: + { + uint32_t status_flags = PARSER_FUNCTION_CLOSURE; + + if (context_p->token.type == LEXER_KEYW_ASYNC) + { + status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + lexer_consume_generator (context_p); + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (has_super_env) + { + status_flags |= PARSER_ALLOW_SUPER; + } + + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS); + + uint16_t opcode = CBC_SET_LITERAL_PROPERTY; + /* This assignment is a nop for CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL. */ + uint16_t literal_index = context_p->lit_object.index; + bool is_computed = context_p->token.type == LEXER_RIGHT_SQUARE; + + if (is_computed) + { + opcode = CBC_EXT_SET_COMPUTED_PROPERTY; + } + + uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags); + + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + if (is_computed) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED); + } + parser_emit_cbc_ext (context_p, opcode); + lexer_next_token (context_p); + break; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, status_flags); + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT); + parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index); + } + else + { + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.value = literal_index; + } + + lexer_next_token (context_p); + break; + } + default: + { + const lexer_lit_location_t *literal_p = (const lexer_lit_location_t *) context_p->lit_object.literal_p; + bool is_proto = ((context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_STRING_LITERAL) + && lexer_compare_identifier_to_string (literal_p, (uint8_t *) "__proto__", 9) + && lexer_check_next_character (context_p, LIT_CHAR_COLON)); + if (is_proto) + { + if (proto_seen) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_PROTO); + } + + proto_seen = true; + } + + uint16_t literal_index = context_p->lit_object.index; + parser_line_counter_t start_line = context_p->token.line; + parser_line_counter_t start_column = context_p->token.column; + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_PAREN && !is_proto) + { + parser_parse_object_method (context_p); + + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + parser_set_function_name (context_p, context_p->last_cbc.literal_index, literal_index, 0); + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT); + parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index); + break; + } + + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + context_p->last_cbc.value = literal_index; + break; + } + + if ((context_p->token.type == LEXER_RIGHT_BRACE || context_p->token.type == LEXER_COMMA) && !is_proto) + { + parser_reparse_as_common_identifier (context_p, start_line, start_column); + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + context_p->last_cbc.value = literal_index; + + lexer_next_token (context_p); + break; + } + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (is_proto) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET__PROTO__); + break; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + if (context_p->last_cbc.literal_type == LEXER_FUNCTION_LITERAL) + { + parser_set_function_name (context_p, context_p->last_cbc.literal_index, literal_index, 0); + } + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; + context_p->last_cbc.value = literal_index; + } + else + { + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS)) + { + uint16_t name_index = scanner_save_literal (context_p, literal_index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + + parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index); + } + + break; + } + } + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + break; + } + else if (context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED); + } + } + + if (has_super_env) + { + parser_emit_cbc_ext (context_p, CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT); + } +} /* parser_parse_object_literal */ + +/** + * Parse function literal. + */ +static void +parser_parse_function_expression (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< function status flags */ +{ + int literals = 0; + uint16_t literal1 = 0; + uint16_t literal2 = 0; + uint16_t function_literal_index; + int32_t function_name_index = -1; + + if (status_flags & PARSER_IS_FUNC_EXPRESSION) + { + uint32_t parent_status_flags = context_p->status_flags; + + context_p->status_flags &= + (uint32_t) ~(PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD); + + if (status_flags & PARSER_IS_ASYNC_FUNCTION) + { + /* The name of the function cannot be await. */ + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (lexer_consume_generator (context_p)) + { + /* The name of the function cannot be yield. */ + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (!lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + /* The `await` keyword is interpreted as an IdentifierReference within function expressions */ + context_p->status_flags &= (uint32_t) ~PARSER_IS_CLASS_STATIC_BLOCK; + + lexer_next_token (context_p); + + context_p->status_flags |= parent_status_flags & PARSER_IS_CLASS_STATIC_BLOCK; + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + parser_flush_cbc (context_p); + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + + if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS) + { + status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + + function_name_index = context_p->lit_object.index; + } + + context_p->status_flags = parent_status_flags; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + literals = 1; + literal1 = context_p->last_cbc.literal_index; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + literals = 2; + literal1 = context_p->last_cbc.literal_index; + literal2 = context_p->last_cbc.value; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + + function_literal_index = lexer_construct_function_object (context_p, status_flags); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + if (function_name_index != -1) + { + parser_set_function_name (context_p, function_literal_index, (uint16_t) function_name_index, 0); + } + + if (literals == 1) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.literal_index = literal1; + context_p->last_cbc.value = function_literal_index; + } + else if (literals == 2) + { + context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; + context_p->last_cbc.literal_index = literal1; + context_p->last_cbc.value = literal2; + context_p->last_cbc.third_literal_index = function_literal_index; + } + else + { + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, function_literal_index); + + if (function_name_index != -1) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION); + context_p->last_cbc.value = (uint16_t) function_name_index; + } + } + + context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; +} /* parser_parse_function_expression */ + +/** + * Parse template literal. + */ +static void +parser_parse_template_literal (parser_context_t *context_p) /**< context */ +{ + bool is_empty_head = true; + + if (context_p->token.lit_location.length > 0) + { + is_empty_head = false; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + + if (!is_empty_head) + { + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS); + } + else if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_STRING_CONCAT); + } + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + if (is_empty_head || context_p->token.lit_location.length > 0) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS); + context_p->last_cbc.value = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; + } + else + { + parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + } + + while (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_STRING_CONCAT); + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + if (context_p->token.lit_location.length > 0) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + + parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_STRING_CONCAT_RIGHT_LITERAL); + } + } +} /* parser_parse_template_literal */ + +/** + * Parse tagged template literal. + */ +static size_t +parser_parse_tagged_template_literal (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_TEMPLATE_LITERAL); + + uint32_t call_arguments = 0; + ecma_collection_t *collection_p; + + if (context_p->tagged_template_literal_cp == JMEM_CP_NULL) + { + collection_p = ecma_new_collection (); + ECMA_SET_INTERNAL_VALUE_POINTER (context_p->tagged_template_literal_cp, collection_p); + } + else + { + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_p->tagged_template_literal_cp); + if (collection_p->item_count > CBC_MAXIMUM_BYTE_VALUE) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + } + + const uint32_t tagged_id = collection_p->item_count; + uint32_t prop_idx = 0; + ecma_object_t *raw_strings_p; + ecma_object_t *template_obj_p = parser_new_tagged_template_literal (&raw_strings_p); + ecma_collection_push_back (collection_p, ecma_make_object_value (template_obj_p)); + + parser_tagged_template_literal_append_strings (context_p, template_obj_p, raw_strings_p, prop_idx++); + + call_arguments++; + parser_emit_cbc_ext_call (context_p, CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, tagged_id); + + while (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + JERRY_ASSERT (context_p->source_p[-1] == LIT_CHAR_LEFT_BRACE); + lexer_next_token (context_p); + + if (++call_arguments > CBC_MAXIMUM_BYTE_VALUE) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + parser_tagged_template_literal_append_strings (context_p, template_obj_p, raw_strings_p, prop_idx++); + } + + parser_tagged_template_literal_finalize (template_obj_p, raw_strings_p); + + return call_arguments; +} /* parser_parse_tagged_template_literal */ + +/** + * Checks wheteher the current expression can be an assignment expression. + * + * @return true if the current expression can be an assignment expression, false otherwise + */ +static inline bool +parser_is_assignment_expr (parser_context_t *context_p) +{ + return (context_p->stack_top_uint8 == LEXER_EXPRESSION_START || context_p->stack_top_uint8 == LEXER_LEFT_PAREN + || context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST + || LEXER_IS_BINARY_LVALUE_OP_TOKEN (context_p->stack_top_uint8)); +} /* parser_is_assignment_expr */ + +/** + * Throws an error if the current expression is not an assignment expression. + */ +static inline void +parser_check_assignment_expr (parser_context_t *context_p) +{ + if (!parser_is_assignment_expr (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_ASSIGNMENT_EXPECTED); + } +} /* parser_check_assignment_expr */ + +/** + * Checks whether the next token is a valid continuation token after an AssignmentExpression. + */ +static inline bool +parser_abort_parsing_after_assignment_expression (parser_context_t *context_p) +{ + return (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_COMMA); +} /* parser_abort_parsing_after_assignment_expression */ + +/** + * Parse and record unary operators, and parse the primary literal. + * + * @return true if parsing should be aborted, true otherwise + */ +static bool +parser_parse_unary_expression (parser_context_t *context_p, /**< context */ + size_t *grouping_level_p) /**< grouping level */ +{ + bool new_was_seen = false; + + /* Collect unary operators. */ + while (true) + { + /* Convert plus and minus binary operators to unary operators. */ + switch (context_p->token.type) + { + case LEXER_ADD: + { + context_p->token.type = LEXER_PLUS; + break; + } + case LEXER_SUBTRACT: + { + context_p->token.type = LEXER_NEGATE; + break; + } + case LEXER_KEYW_AWAIT: + { +#if JERRY_MODULE_SYSTEM + if ((context_p->global_status_flags & ECMA_PARSE_MODULE) + && !(context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)) + { + parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED); + } +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + break; + } + } + + /* Bracketed expressions are primary expressions. At this + * point their left paren is pushed onto the stack and + * they are processed when their closing paren is reached. */ + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + break; + } + (*grouping_level_p) += PARSER_GROUPING_LEVEL_INCREASE; + new_was_seen = false; + } + else if (context_p->token.type == LEXER_KEYW_NEW) + { + /* After 'new' unary operators are not allowed. */ + new_was_seen = true; + + /* Check if "new.target" is written here. */ + if (scanner_try_scan_new_target (context_p)) + { + if (!(context_p->status_flags & PARSER_ALLOW_NEW_TARGET)) + { + parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_NOT_ALLOWED); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_NEW_TARGET); + lexer_next_token (context_p); + /* Found "new.target" return here */ + return false; + } + } + else if (new_was_seen || (*grouping_level_p == PARSE_EXPR_LEFT_HAND_SIDE) + || !LEXER_IS_UNARY_OP_TOKEN (context_p->token.type)) + { + break; + } + + parser_stack_push_uint8 (context_p, context_p->token.type); + lexer_next_token (context_p); + } + + /* Parse primary expression. */ + switch (context_p->token.type) + { + case LEXER_HASHMARK: + { + if (!lexer_scan_private_identifier (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + + parser_resolve_private_identifier (context_p); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_KEYW_IN) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + + parser_stack_push_uint16 (context_p, context_p->lit_object.index); + parser_stack_push_uint8 (context_p, LEXER_PRIVATE_PRIMARY_EXPR); + return false; + } + case LEXER_TEMPLATE_LITERAL: + { + if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + parser_parse_template_literal (context_p); + break; + } + + /* The string is a normal string literal. */ + /* FALLTHRU */ + } + case LEXER_LITERAL: + { + if (JERRY_UNLIKELY (context_p->next_scanner_info_p->source_p == context_p->source_p)) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + uint32_t arrow_status_flags = + (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION + | (context_p->status_flags & (PARSER_INSIDE_CLASS_FIELD | PARSER_IS_CLASS_STATIC_BLOCK))); + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC) + { + JERRY_ASSERT (lexer_token_is_async (context_p)); + JERRY_ASSERT (!(context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT)); + + uint32_t saved_status_flags = context_p->status_flags; + + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + lexer_next_token (context_p); + context_p->status_flags = saved_status_flags; + + if (context_p->token.type == LEXER_KEYW_FUNCTION) + { + uint32_t status_flags = (PARSER_FUNCTION_CLOSURE | PARSER_IS_FUNC_EXPRESSION | PARSER_IS_ASYNC_FUNCTION + | PARSER_DISALLOW_AWAIT_YIELD); + parser_parse_function_expression (context_p, status_flags); + break; + } + + arrow_status_flags = + (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION | PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD); + } + + parser_check_assignment_expr (context_p); + parser_parse_function_expression (context_p, arrow_status_flags); + return parser_abort_parsing_after_assignment_expression (context_p); + } + + uint8_t type = context_p->token.lit_location.type; + + if (type == LEXER_IDENT_LITERAL || type == LEXER_STRING_LITERAL) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, context_p->token.lit_location.type); + } + else if (type == LEXER_NUMBER_LITERAL) + { + bool is_negative_number = false; + + if ((context_p->stack_top_uint8 == LEXER_PLUS || context_p->stack_top_uint8 == LEXER_NEGATE) + && !lexer_check_post_primary_exp (context_p)) + { + do + { + if (context_p->stack_top_uint8 == LEXER_NEGATE) + { + is_negative_number = !is_negative_number; + } +#if JERRY_BUILTIN_BIGINT + else if (JERRY_LIKELY (context_p->token.extra_value == LEXER_NUMBER_BIGINT)) + { + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + parser_stack_pop_uint8 (context_p); + } while (context_p->stack_top_uint8 == LEXER_PLUS || context_p->stack_top_uint8 == LEXER_NEGATE); + } + + if (lexer_construct_number_object (context_p, true, is_negative_number)) + { + JERRY_ASSERT (context_p->lit_object.index <= CBC_PUSH_NUMBER_BYTE_RANGE_END); + + parser_emit_cbc_push_number (context_p, is_negative_number); + break; + } + } + + cbc_opcode_t opcode = CBC_PUSH_LITERAL; + + if (context_p->token.keyword_type != LEXER_KEYW_EVAL) + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.value = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; + break; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; + context_p->last_cbc.third_literal_index = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; + break; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_THIS) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_PUSH_THIS_LITERAL; + } + } + + parser_emit_cbc_literal_from_token (context_p, (uint16_t) opcode); + break; + } + case LEXER_KEYW_FUNCTION: + { +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + parser_parse_function_expression (context_p, PARSER_FUNCTION_CLOSURE | PARSER_IS_FUNC_EXPRESSION); + break; + } + case LEXER_LEFT_BRACE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (parser_is_assignment_expr (context_p)) + { + uint32_t flags = PARSER_PATTERN_NO_OPTS; + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + + parser_parse_object_initializer (context_p, (parser_pattern_flags_t) flags); + return parser_abort_parsing_after_assignment_expression (context_p); + } + + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + + parser_parse_object_literal (context_p); + break; + } + case LEXER_LEFT_SQUARE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (parser_is_assignment_expr (context_p)) + { + parser_parse_array_initializer (context_p, PARSER_PATTERN_NO_OPTS); + return parser_abort_parsing_after_assignment_expression (context_p); + } + + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS + && context_p->next_scanner_info_p->u8_arg == SCANNER_LITERAL_NO_DESTRUCTURING); + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + parser_parse_array_literal (context_p); + break; + } + case LEXER_DIVIDE: + case LEXER_ASSIGN_DIVIDE: + { + lexer_construct_regexp_object (context_p, false); + uint16_t literal_index = (uint16_t) (context_p->literal_count - 1); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.value = literal_index; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; + context_p->last_cbc.third_literal_index = literal_index; + } + else + { + parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, literal_index); + } + + context_p->last_cbc.literal_type = LEXER_REGEXP_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; + break; + } + case LEXER_KEYW_THIS: + { + if (context_p->status_flags & PARSER_ALLOW_SUPER_CALL) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RESOLVE_LEXICAL_THIS); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_THIS); + } + + break; + } + case LEXER_LIT_TRUE: + { + parser_emit_cbc (context_p, CBC_PUSH_TRUE); + break; + } + case LEXER_LIT_FALSE: + { + parser_emit_cbc (context_p, CBC_PUSH_FALSE); + break; + } + case LEXER_LIT_NULL: + { + parser_emit_cbc (context_p, CBC_PUSH_NULL); + break; + } + case LEXER_KEYW_CLASS: + { + parser_parse_class (context_p, false); + return false; + } + case LEXER_KEYW_SUPER: + { + if (context_p->status_flags & PARSER_ALLOW_SUPER) + { + if (lexer_check_next_characters (context_p, LIT_CHAR_DOT, LIT_CHAR_LEFT_SQUARE)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER); + break; + } + + if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN) + && (context_p->status_flags & PARSER_ALLOW_SUPER_CALL)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER_CONSTRUCTOR); + break; + } + } + + parser_raise_error (context_p, PARSER_ERR_UNEXPECTED_SUPER_KEYWORD); + } + case LEXER_LEFT_PAREN: + { + JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + parser_check_assignment_expr (context_p); + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->source_p - 1; +#endif /* JERRY_FUNCTION_TO_STRING */ + + uint32_t arrow_status_flags = + (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION + | (context_p->status_flags & (PARSER_INSIDE_CLASS_FIELD | PARSER_IS_CLASS_STATIC_BLOCK))); + parser_parse_function_expression (context_p, arrow_status_flags); + return parser_abort_parsing_after_assignment_expression (context_p); + } + case LEXER_KEYW_YIELD: + { + JERRY_ASSERT ((context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + && !(context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD)); + + if (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + + parser_check_assignment_expr (context_p); + lexer_next_token (context_p); + + cbc_ext_opcode_t opcode = + ((context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) ? CBC_EXT_ASYNC_YIELD : CBC_EXT_YIELD); + if (!lexer_check_yield_no_arg (context_p)) + { + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_next_token (context_p); + opcode = ((context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) ? CBC_EXT_ASYNC_YIELD_ITERATOR + : CBC_EXT_YIELD_ITERATOR); + } + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + } + + parser_emit_cbc_ext (context_p, opcode); + + return (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_COMMA); + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_DOT) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL + || context_p->token.keyword_type != LEXER_KEYW_META + || (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_META_EXPECTED); + } + + if (!(context_p->global_status_flags & ECMA_PARSE_MODULE)) + { + parser_raise_error (context_p, PARSER_ERR_IMPORT_META_REQUIRE_MODULE); + } + + JERRY_ASSERT (context_p->global_status_flags & ECMA_PARSE_INTERNAL_HAS_IMPORT_META); + + parser_emit_cbc_ext (context_p, CBC_EXT_MODULE_IMPORT_META); + break; + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + if (new_was_seen) + { + parser_raise_error (context_p, PARSER_ERR_IMPORT_AFTER_NEW); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_MODULE_IMPORT); + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + bool is_left_hand_side = (*grouping_level_p == PARSE_EXPR_LEFT_HAND_SIDE); + parser_raise_error (context_p, + (is_left_hand_side ? PARSER_ERR_LEFT_HAND_SIDE_EXP_EXPECTED : PARSER_ERR_UNEXPECTED_END)); + break; + } + } + lexer_next_token (context_p); + return false; +} /* parser_parse_unary_expression */ + +/** + * Parse the postfix part of unary operators, and + * generate byte code for the whole expression. + */ +static void +parser_process_unary_expression (parser_context_t *context_p, /**< context */ + size_t grouping_level) /**< grouping level */ +{ + /* Parse postfix part of a primary expression. */ + while (true) + { + /* Since break would only break the switch, we use + * continue to continue this loop. Without continue, + * the code abandons the loop. */ + switch (context_p->token.type) + { + case LEXER_DOT: + { + parser_push_result (context_p); + + if (lexer_check_next_character (context_p, LIT_CHAR_HASHMARK)) + { + lexer_next_token (context_p); + + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + parser_raise_error (context_p, PARSER_ERR_UNEXPECTED_PRIVATE_FIELD); + } + + if (!lexer_scan_private_identifier (context_p)) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + parser_resolve_private_identifier (context_p); + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_PRIVATE_PROP_LITERAL, context_p->lit_object.index); + lexer_next_token (context_p); + continue; + } + + lexer_expect_identifier (context_p, LEXER_STRING_LITERAL); + + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->lit_object.literal_p->type == LEXER_STRING_LITERAL); + context_p->token.lit_location.type = LEXER_STRING_LITERAL; + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + JERRY_ASSERT (CBC_ARGS_EQ (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + context_p->last_cbc_opcode = CBC_PUSH_PROP_LITERAL_LITERAL; + context_p->last_cbc.value = context_p->lit_object.index; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THIS) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_PROP_THIS_LITERAL); + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL); + context_p->last_cbc.literal_index = context_p->lit_object.index; + } + else + { + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_PROP_LITERAL); + } + lexer_next_token (context_p); + continue; + } + + case LEXER_LEFT_SQUARE: + { + parser_push_result (context_p); + + uint16_t last_cbc_opcode = context_p->last_cbc_opcode; + + if (last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_SQUARE_EXPECTED); + } + lexer_next_token (context_p); + + if (last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER_PROP); + continue; + } + + if (PARSER_IS_MUTABLE_PUSH_LITERAL (context_p->last_cbc_opcode)) + { + context_p->last_cbc_opcode = PARSER_PUSH_LITERAL_TO_PUSH_PROP_LITERAL (context_p->last_cbc_opcode); + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_PROP); + } + continue; + } + case LEXER_TEMPLATE_LITERAL: + case LEXER_LEFT_PAREN: + { + size_t call_arguments = 0; + uint16_t opcode = CBC_CALL; + bool is_eval = false; + + parser_push_result (context_p); + + if (context_p->stack_top_uint8 == LEXER_KEYW_NEW) + { + if (context_p->token.type == LEXER_LEFT_PAREN) + { + parser_stack_pop_uint8 (context_p); + opcode = CBC_NEW; + } + } + else + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL + && context_p->last_cbc.literal_keyword_type == LEXER_KEYW_EVAL + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + is_eval = true; + } + + if (PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)) + { + opcode = CBC_CALL_PROP; + context_p->last_cbc_opcode = PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE (context_p->last_cbc_opcode); + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR)) + { + opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL); + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE); + opcode = CBC_CALL_PROP; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE); + opcode = CBC_CALL_PROP; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE); + opcode = CBC_CALL_PROP; + } + else if (JERRY_UNLIKELY (context_p->status_flags & PARSER_INSIDE_WITH) + && PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + opcode = CBC_CALL_PROP; + parser_emit_ident_reference (context_p, CBC_PUSH_IDENT_REFERENCE); + parser_emit_cbc_ext (context_p, CBC_EXT_RESOLVE_BASE); + } + } + + bool has_spread_element = false; + + if (context_p->token.type == LEXER_TEMPLATE_LITERAL) + { + call_arguments = parser_parse_tagged_template_literal (context_p); + } + else + { + lexer_next_token (context_p); + + while (context_p->token.type != LEXER_RIGHT_PAREN) + { + if (++call_arguments > CBC_MAXIMUM_BYTE_VALUE) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + if (context_p->token.type == LEXER_THREE_DOTS) + { + has_spread_element = true; + call_arguments++; + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SPREAD_ELEMENT); + lexer_next_token (context_p); + } + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + continue; + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + break; + } + } + + lexer_next_token (context_p); + + if (is_eval) + { + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + + uint16_t eval_flags = PARSER_SAVE_STATUS_FLAGS (context_p->status_flags); + const uint32_t required_flags = PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED; + + if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS) + { + context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + else if (((context_p->status_flags & (required_flags | PARSER_IS_STRICT)) == required_flags) + || ((context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + && !(context_p->status_flags & PARSER_IS_FUNCTION))) + { + eval_flags |= PARSER_GET_EVAL_FLAG (ECMA_PARSE_FUNCTION_CONTEXT); + } + + if (eval_flags != 0) + { + parser_emit_cbc_ext_call (context_p, CBC_EXT_LOCAL_EVAL, eval_flags); + } + else + { + parser_emit_cbc (context_p, CBC_EVAL); + } + } + + if (has_spread_element) + { + uint16_t spread_opcode; + + if (opcode == CBC_CALL) + { + spread_opcode = CBC_EXT_SPREAD_CALL; + } + else if (opcode == CBC_CALL_PROP) + { + spread_opcode = CBC_EXT_SPREAD_CALL_PROP; + } + else if (opcode == CBC_NEW) + { + spread_opcode = CBC_EXT_SPREAD_NEW; + } + else + { + /* opcode is unchanged */ + JERRY_ASSERT (opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL)); + spread_opcode = CBC_EXT_SPREAD_SUPER_CALL; + } + + parser_emit_cbc_ext_call (context_p, spread_opcode, call_arguments); + continue; + } + + if (call_arguments <= 1) + { + if (opcode == CBC_CALL) + { + parser_emit_cbc (context_p, (uint16_t) (CBC_CALL0 + (call_arguments * 6))); + continue; + } + if (opcode == CBC_CALL_PROP) + { + parser_emit_cbc (context_p, (uint16_t) (CBC_CALL0_PROP + (call_arguments * 6))); + continue; + } + if (opcode == CBC_NEW) + { + parser_emit_cbc (context_p, (uint16_t) (CBC_NEW0 + call_arguments)); + continue; + } + } + else if (call_arguments == 2) + { + if (opcode == CBC_CALL) + { + parser_emit_cbc (context_p, CBC_CALL2); + continue; + } + if (opcode == CBC_CALL_PROP) + { + parser_flush_cbc (context_p); + /* Manually adjusting stack usage. */ + JERRY_ASSERT (context_p->stack_depth > 0); + context_p->stack_depth--; + parser_emit_cbc (context_p, CBC_CALL2_PROP); + continue; + } + } + + parser_emit_cbc_call (context_p, opcode, call_arguments); + continue; + } + default: + { + if (context_p->stack_top_uint8 == LEXER_KEYW_NEW) + { + parser_push_result (context_p); + parser_emit_cbc (context_p, CBC_NEW0); + parser_stack_pop_uint8 (context_p); + continue; + } + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) + && (context_p->token.type == LEXER_INCREASE || context_p->token.type == LEXER_DECREASE) + && grouping_level != PARSE_EXPR_LEFT_HAND_SIDE) + { + cbc_opcode_t opcode = (context_p->token.type == LEXER_INCREASE) ? CBC_POST_INCR : CBC_POST_DECR; + parser_push_result (context_p); + parser_emit_unary_lvalue_opcode (context_p, opcode); + lexer_next_token (context_p); + } + break; + } + } + break; + } + + uint8_t last_unary_token = LEXER_INCREASE; + + /* Generate byte code for the unary operators. */ + while (true) + { + uint8_t token = context_p->stack_top_uint8; + if (!LEXER_IS_UNARY_OP_TOKEN (token)) + { + if (context_p->token.type == LEXER_EXPONENTIATION && last_unary_token != LEXER_INCREASE + && last_unary_token != LEXER_DECREASE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_EXPONENTIATION); + } + + break; + } + + last_unary_token = token; + parser_push_result (context_p); + parser_stack_pop_uint8 (context_p); + + if (LEXER_IS_UNARY_LVALUE_OP_TOKEN (token)) + { + if (token == LEXER_KEYW_DELETE) + { + token = CBC_DELETE_PUSH_RESULT; + } + else + { + token = (uint8_t) (LEXER_UNARY_LVALUE_OP_TOKEN_TO_OPCODE (token)); + } + parser_emit_unary_lvalue_opcode (context_p, (cbc_opcode_t) token); + } + else if (JERRY_UNLIKELY (token == LEXER_KEYW_AWAIT)) + { + cbc_ext_opcode_t opcode = + ((context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) ? CBC_EXT_GENERATOR_AWAIT : CBC_EXT_AWAIT); + parser_emit_cbc_ext (context_p, opcode); + } + else + { + token = (uint8_t) (LEXER_UNARY_OP_TOKEN_TO_OPCODE (token)); + + if (token == CBC_TYPEOF) + { + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_emit_ident_reference (context_p, CBC_TYPEOF_IDENT); + } + else + { + parser_emit_cbc (context_p, token); + } + } + else + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + /* It is not worth to combine with push multiple literals + * since the byte code size will not decrease. */ + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, token + 1)); + context_p->last_cbc_opcode = (uint16_t) (token + 1); + } + else + { + parser_emit_cbc (context_p, token); + } + } + } + } +} /* parser_process_unary_expression */ + +/** + * Append a binary '=' token. + * + * @return - pushed assignment opcode onto the parser stack + */ +static void +parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */ + uint32_t pattern_flags) /**< pattern flags */ +{ + JERRY_UNUSED (pattern_flags); + + /* Unlike other tokens, the whole byte code is saved for binary + * assignment, since it has multiple forms depending on the + * previous instruction. */ + + uint8_t assign_opcode = CBC_ASSIGN; + + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_check_invalid_assign (context_p); + + uint16_t literal_index; + + switch (context_p->last_cbc_opcode) + { + case CBC_PUSH_LITERAL: + { + literal_index = context_p->last_cbc.literal_index; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + break; + } + case CBC_PUSH_TWO_LITERALS: + { + literal_index = context_p->last_cbc.value; + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + break; + } + case CBC_PUSH_THIS_LITERAL: + { + literal_index = context_p->last_cbc.literal_index; + context_p->last_cbc_opcode = CBC_PUSH_THIS; + parser_flush_cbc (context_p); + break; + } + default: + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS); + literal_index = context_p->last_cbc.third_literal_index; + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + break; + } + } + + assign_opcode = CBC_ASSIGN_SET_IDENT; + + if (!(pattern_flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST | PARSER_PATTERN_LOCAL))) + { + if (scanner_literal_is_const_reg (context_p, literal_index)) + { + parser_stack_push_uint8 (context_p, LEXER_ASSIGN_CONST); + } + } + else if (literal_index < PARSER_REGISTER_START) + { + assign_opcode = CBC_INIT_LET; + + if (scanner_literal_is_created (context_p, literal_index)) + { + assign_opcode = CBC_ASSIGN_LET_CONST; + } + else if (pattern_flags & PARSER_PATTERN_CONST) + { + assign_opcode = CBC_INIT_CONST; + } + else if (pattern_flags & PARSER_PATTERN_LOCAL) + { + assign_opcode = CBC_INIT_ARG_OR_CATCH; + } + } + + parser_stack_push_uint16 (context_p, literal_index); + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, assign_opcode)); + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, CBC_ASSIGN)); + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL) + { + if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL, CBC_ASSIGN_PROP_LITERAL)); + parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index); + assign_opcode = CBC_ASSIGN_PROP_LITERAL; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + } + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_PUSH_TWO_LITERALS)); + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_THIS_LITERAL) + { + if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_THIS_LITERAL, CBC_ASSIGN_PROP_THIS_LITERAL)); + parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index); + assign_opcode = CBC_ASSIGN_PROP_THIS_LITERAL; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else + { + context_p->last_cbc_opcode = CBC_PUSH_THIS_LITERAL; + } + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE); + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_SUPER); + assign_opcode = CBC_EXT_OPCODE; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP)) + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE); + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_SUPER); + assign_opcode = CBC_EXT_OPCODE; + } + else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL)) + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_PRIVATE); + assign_opcode = CBC_EXT_OPCODE; + } + else + { + /* Invalid LeftHandSide expression. */ // 3820, 3815 + parser_check_invalid_new_target (context_p, CBC_ASSIGN); + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT); + } + + parser_stack_push_uint8 (context_p, assign_opcode); + parser_stack_push_uint8 (context_p, LEXER_ASSIGN); +} /* parser_append_binary_single_assignment_token */ + +/** + * Check for invalid chain of logical operators + */ +static void +parser_check_invalid_logical_op (parser_context_t *context_p, /**< context */ + uint8_t invalid_token1, /**< token id of first invalid token */ + uint8_t invalid_token2) /**< token id of second invalid token */ +{ + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + while (true) + { + uint8_t token = parser_stack_iterator_read_uint8 (&iterator); + + if (!LEXER_IS_BINARY_NON_LVALUE_OP_TOKEN (token)) + { + return; + } + + if (token == invalid_token1 || token == invalid_token2) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_NULLISH_COALESCING); + } + + /* If a logical operator is found, and there is no SyntaxError, the scan can be terminated + * since there was no SyntaxError when the logical operator was pushed onto the stack. */ + if (token == LEXER_LOGICAL_OR || token == LEXER_LOGICAL_AND || token == LEXER_NULLISH_COALESCING) + { + return; + } + + parser_stack_iterator_skip (&iterator, sizeof (uint8_t)); + } +} /* parser_check_invalid_logical_op */ + +/** + * Append a binary lvalue token. + */ +static void +parser_append_binary_lvalue_token (parser_context_t *context_p, /**< context */ + bool is_logical_assignment) /**< true - if form logical assignment reference + * false - otherwise */ +{ + if (PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + parser_check_invalid_assign (context_p); + + parser_emit_ident_reference (context_p, CBC_PUSH_IDENT_REFERENCE); + + if (!is_logical_assignment && scanner_literal_is_const_reg (context_p, context_p->last_cbc.literal_index)) + { + parser_stack_push_uint8 (context_p, LEXER_ASSIGN_CONST); + } + } + else if (PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)) + { + context_p->last_cbc_opcode = PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE (context_p->last_cbc_opcode); + } + else + { + /* Invalid LeftHandSide expression. */ + parser_check_invalid_new_target (context_p, CBC_ASSIGN); + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT); + parser_emit_cbc (context_p, CBC_PUSH_PROP_REFERENCE); + } + + if (!is_logical_assignment) + { + parser_stack_push_uint8 (context_p, (uint8_t) context_p->token.type); + } +} /* parser_append_binary_lvalue_token */ + +/** + * Append a logical token. + */ +static void +parser_append_logical_token (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + if (opcode != PARSER_TO_EXT_OPCODE (CBC_EXT_BRANCH_IF_NULLISH)) + { + parser_check_invalid_logical_op (context_p, LEXER_NULLISH_COALESCING, LEXER_NULLISH_COALESCING); + } + + parser_branch_t branch; + parser_emit_cbc_forward_branch (context_p, opcode, &branch); + parser_stack_push (context_p, &branch, sizeof (parser_branch_t)); + parser_stack_push_uint8 (context_p, (uint8_t) context_p->token.type); +} /* parser_append_logical_token */ + +/** + * Append a logical token. + */ +static void +parser_append_logical_assignment_token (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + uint16_t last_cbc_opcode = context_p->last_cbc_opcode; + parser_append_binary_single_assignment_token (context_p, 0); + parser_stack_change_last_uint8 (context_p, LEXER_ASSIGN_REFERENCE); + context_p->last_cbc_opcode = last_cbc_opcode; + + parser_append_binary_lvalue_token (context_p, true); + parser_append_logical_token (context_p, opcode); +} /* parser_append_logical_assignment_token */ + +/** + * Append a binary token. + */ +static void +parser_append_binary_token (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type)); + parser_push_result (context_p); + + switch (context_p->token.type) + { + case LEXER_ASSIGN: + { + parser_append_binary_single_assignment_token (context_p, 0); + break; + } + /* Binary lvalue-opcodes */ + case LEXER_ASSIGN_ADD: + case LEXER_ASSIGN_SUBTRACT: + case LEXER_ASSIGN_MULTIPLY: + case LEXER_ASSIGN_DIVIDE: + case LEXER_ASSIGN_MODULO: + case LEXER_ASSIGN_EXPONENTIATION: + case LEXER_ASSIGN_LEFT_SHIFT: + case LEXER_ASSIGN_RIGHT_SHIFT: + case LEXER_ASSIGN_UNS_RIGHT_SHIFT: + case LEXER_ASSIGN_BIT_AND: + case LEXER_ASSIGN_BIT_OR: + case LEXER_ASSIGN_BIT_XOR: + { + parser_append_binary_lvalue_token (context_p, false); + break; + } + case LEXER_ASSIGN_NULLISH_COALESCING: + { + parser_append_logical_assignment_token (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_BRANCH_IF_NULLISH)); + break; + } + case LEXER_ASSIGN_LOGICAL_OR: + { + parser_append_logical_assignment_token (context_p, CBC_BRANCH_IF_LOGICAL_TRUE); + break; + } + case LEXER_ASSIGN_LOGICAL_AND: + { + parser_append_logical_assignment_token (context_p, CBC_BRANCH_IF_LOGICAL_FALSE); + break; + } + case LEXER_NULLISH_COALESCING: + { + parser_append_logical_token (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_BRANCH_IF_NULLISH)); + break; + } + case LEXER_LOGICAL_OR: + { + parser_append_logical_token (context_p, CBC_BRANCH_IF_LOGICAL_TRUE); + break; + } + case LEXER_LOGICAL_AND: + { + parser_append_logical_token (context_p, CBC_BRANCH_IF_LOGICAL_FALSE); + break; + } + default: + { + parser_stack_push_uint8 (context_p, (uint8_t) context_p->token.type); + break; + } + } +} /* parser_append_binary_token */ + +/** + * Emit opcode for binary assignment token. + */ +static void +parser_process_binary_assignment_token (parser_context_t *context_p, /**< context */ + uint8_t token) /**< token */ +{ + uint16_t index = PARSER_INVALID_LITERAL_INDEX; + uint16_t opcode = context_p->stack_top_uint8; + + if (JERRY_UNLIKELY (opcode == CBC_EXT_OPCODE)) + { + parser_stack_pop_uint8 (context_p); + JERRY_ASSERT (context_p->stack_top_uint8 == CBC_EXT_ASSIGN_SUPER + || context_p->stack_top_uint8 == CBC_EXT_ASSIGN_PRIVATE); + opcode = PARSER_TO_EXT_OPCODE (context_p->stack_top_uint8); + parser_stack_pop_uint8 (context_p); + } + else + { + parser_stack_pop_uint8 (context_p); + + if (cbc_flags[opcode] & CBC_HAS_LITERAL_ARG) + { + JERRY_ASSERT (opcode == CBC_ASSIGN_SET_IDENT || opcode == CBC_ASSIGN_PROP_LITERAL + || opcode == CBC_ASSIGN_PROP_THIS_LITERAL || opcode == CBC_ASSIGN_LET_CONST + || opcode == CBC_INIT_ARG_OR_CATCH || opcode == CBC_INIT_LET || opcode == CBC_INIT_CONST); + + index = parser_stack_pop_uint16 (context_p); + } + } + + bool group_expr_assingment = false; + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == LEXER_ASSIGN_GROUP_EXPR)) + { + group_expr_assingment = true; + parser_stack_pop_uint8 (context_p); + } + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == LEXER_ASSIGN_CONST)) + { + parser_stack_pop_uint8 (context_p); + parser_emit_cbc_ext (context_p, CBC_EXT_THROW_ASSIGN_CONST_ERROR); + } + + if (index == PARSER_INVALID_LITERAL_INDEX) + { + if (JERRY_UNLIKELY (token == LEXER_ASSIGN_REFERENCE)) + { + opcode = CBC_ASSIGN_PUSH_RESULT; + } + + parser_emit_cbc (context_p, opcode); + return; + } + + if (!group_expr_assingment) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + uint16_t name_index = scanner_save_literal (context_p, index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, (uint16_t) index, 0); + } + } + + if (JERRY_UNLIKELY (token == LEXER_ASSIGN_REFERENCE)) + { + parser_emit_cbc (context_p, CBC_ASSIGN_PUSH_RESULT); + return; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL && opcode == CBC_ASSIGN_SET_IDENT) + { + JERRY_ASSERT (CBC_ARGS_EQ (CBC_ASSIGN_LITERAL_SET_IDENT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + + context_p->last_cbc.value = index; + context_p->last_cbc_opcode = CBC_ASSIGN_LITERAL_SET_IDENT; + return; + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, index); + + if (opcode == CBC_ASSIGN_PROP_THIS_LITERAL && (context_p->stack_depth >= context_p->stack_limit)) + { + /* Stack limit is increased for VM_OC_ASSIGN_PROP_THIS. Needed by vm.c. */ + JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit); + + context_p->stack_limit++; + + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } +} /* parser_process_binary_opcodes */ + +/** + * Emit opcode for logical tokens. + */ +static void +parser_process_logical_token (parser_context_t *context_p) /**< context */ +{ + parser_branch_t branch; + parser_stack_pop (context_p, &branch, sizeof (parser_branch_t)); + parser_set_branch_to_current_position (context_p, &branch); +} /* parser_process_logical_token */ + +/** + * Emit opcode for logical assignment tokens. + */ +static void +parser_process_logical_assignment_token (parser_context_t *context_p) /**< context */ +{ + parser_branch_t condition_branch; + parser_stack_pop (context_p, &condition_branch, sizeof (parser_branch_t)); + + uint8_t token = context_p->stack_top_uint8; + JERRY_ASSERT (token == LEXER_ASSIGN_REFERENCE); + parser_stack_pop_uint8 (context_p); + parser_process_binary_assignment_token (context_p, token); + + parser_branch_t prop_reference_branch; + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &prop_reference_branch); + + parser_set_branch_to_current_position (context_p, &condition_branch); + parser_emit_cbc_ext (context_p, CBC_EXT_POP_REFERENCE); + + JERRY_ASSERT (context_p->stack_limit - context_p->stack_depth >= 2); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, 2); + + parser_set_branch_to_current_position (context_p, &prop_reference_branch); +} /* parser_process_logical_assignment_token */ + +/** + * Emit opcode for binary tokens. + */ +static void +parser_process_binary_token (parser_context_t *context_p, /**< context */ + uint8_t token) /**< token */ +{ + uint16_t opcode = LEXER_BINARY_OP_TOKEN_TO_OPCODE (token); + + if (PARSER_IS_PUSH_NUMBER (context_p->last_cbc_opcode)) + { + lexer_convert_push_number_to_push_literal (context_p); + } + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, opcode + CBC_BINARY_WITH_LITERAL)); + context_p->last_cbc_opcode = (uint16_t) (opcode + CBC_BINARY_WITH_LITERAL); + return; + } + + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + JERRY_ASSERT (CBC_ARGS_EQ (opcode + CBC_BINARY_WITH_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + context_p->last_cbc_opcode = (uint16_t) (opcode + CBC_BINARY_WITH_TWO_LITERALS); + return; + } + + parser_emit_cbc (context_p, opcode); +} /* parser_process_binary_token */ + +/** + * Emit opcode for binary lvalue tokens. + */ +static void +parser_process_binary_lvalue_token (parser_context_t *context_p, /**< context */ + uint8_t token) /**< token */ +{ + parser_stack_push_uint8 (context_p, CBC_ASSIGN); + parser_stack_push_uint8 (context_p, LEXER_ASSIGN); + parser_stack_push_uint8 (context_p, lexer_convert_binary_lvalue_token_to_binary (token)); +} /* parser_process_binary_lvalue_token */ + +/** + * Emit opcode for binary computations. + */ +static void +parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ + uint8_t min_prec_treshold) /**< minimal precedence of tokens */ +{ + while (true) + { + uint8_t token = context_p->stack_top_uint8; + + /* For left-to-right operators (all binary operators except assignment + * and logical operators), the byte code is flushed if the precedence + * of the next operator is less or equal than the current operator. For + * assignment and logical operators, we add 1 to the min precendence to + * force right-to-left evaluation order. */ + + if (!LEXER_IS_BINARY_OP_TOKEN (token) + || parser_binary_precedence_table[token - LEXER_FIRST_BINARY_OP] < min_prec_treshold) + { + return; + } + + parser_push_result (context_p); + parser_stack_pop_uint8 (context_p); + + switch (token) + { + case LEXER_ASSIGN: + { + parser_process_binary_assignment_token (context_p, token); + continue; + } + /* Binary lvalue-opcodes */ + case LEXER_ASSIGN_ADD: + case LEXER_ASSIGN_SUBTRACT: + case LEXER_ASSIGN_MULTIPLY: + case LEXER_ASSIGN_DIVIDE: + case LEXER_ASSIGN_MODULO: + case LEXER_ASSIGN_EXPONENTIATION: + case LEXER_ASSIGN_LEFT_SHIFT: + case LEXER_ASSIGN_RIGHT_SHIFT: + case LEXER_ASSIGN_UNS_RIGHT_SHIFT: + case LEXER_ASSIGN_BIT_AND: + case LEXER_ASSIGN_BIT_OR: + case LEXER_ASSIGN_BIT_XOR: + { + parser_process_binary_lvalue_token (context_p, token); + continue; + } + case LEXER_ASSIGN_NULLISH_COALESCING: + case LEXER_ASSIGN_LOGICAL_OR: + case LEXER_ASSIGN_LOGICAL_AND: + { + parser_process_logical_assignment_token (context_p); + continue; + } + case LEXER_NULLISH_COALESCING: + case LEXER_LOGICAL_OR: + case LEXER_LOGICAL_AND: + { + parser_process_logical_token (context_p); + continue; + } + case LEXER_KEYW_IN: + { + if (context_p->stack_top_uint8 == LEXER_PRIVATE_PRIMARY_EXPR) + { + parser_stack_pop_uint8 (context_p); + uint16_t lit_id = parser_stack_pop_uint16 (context_p); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN, lit_id); + continue; + } + + /* FALLTHRU */ + } + default: + { + parser_process_binary_token (context_p, token); + continue; + } + } + } +} /* parser_process_binary_opcodes */ + +/** + * End position marker of a pattern. + */ +typedef struct +{ + scanner_location_t location; /**< end position of the pattern */ + lexer_token_t token; /**< token at the end position */ +} parser_pattern_end_marker_t; + +/** + * Literal index should not be emitted while processing rhs target value + */ +#define PARSER_PATTERN_RHS_NO_LIT PARSER_INVALID_LITERAL_INDEX + +/** + * Process the target of an initializer pattern. + */ +static parser_pattern_end_marker_t +parser_pattern_get_target (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + parser_pattern_end_marker_t end_marker; + end_marker.token.type = LEXER_INVALID_PATTERN; + parser_branch_t skip_init; + + if (flags & PARSER_PATTERN_TARGET_DEFAULT) + { + JERRY_ASSERT (flags & PARSER_PATTERN_TARGET_ON_STACK); + + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init); + } + + if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK) + { + scanner_location_t start_location; + + if (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED || (flags & PARSER_PATTERN_REST_ELEMENT)) + { + /* Found invalid pattern, push null value to fake the rhs target. */ + parser_emit_cbc (context_p, CBC_PUSH_NULL); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER); + scanner_get_location (&start_location, context_p); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + scanner_get_location (&(end_marker.location), context_p); + end_marker.token = context_p->token; + + scanner_set_location (context_p, &start_location); + scanner_seek (context_p); + parser_flush_cbc (context_p); + } + } + + if (flags & PARSER_PATTERN_TARGET_DEFAULT) + { + parser_set_branch_to_current_position (context_p, &skip_init); + } + + return end_marker; +} /* parser_pattern_get_target */ + +/** + * Finalize an assignment/binding pattern. + */ +static void +parser_pattern_finalize (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + parser_pattern_end_marker_t *end_marker_p) /**< pattern end position */ +{ + if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK) + { + if (end_marker_p->token.type == LEXER_INVALID_PATTERN) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + + scanner_set_location (context_p, &(end_marker_p->location)); + context_p->token = end_marker_p->token; + } + else + { + JERRY_ASSERT (!(flags & PARSER_PATTERN_TARGET_DEFAULT)); + lexer_next_token (context_p); + } + + if ((flags & (PARSER_PATTERN_BINDING | PARSER_PATTERN_NESTED_PATTERN)) == PARSER_PATTERN_BINDING) + { + /* Pop the result of the expression. */ + parser_emit_cbc (context_p, CBC_POP); + } + + parser_flush_cbc (context_p); +} /* parser_pattern_finalize */ + +/** + * Emit right-hand-side target value. + */ +static void +parser_pattern_emit_rhs (parser_context_t *context_p, /**< context */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index) /**< literal index for object pattern */ +{ + if (literal_index != PARSER_PATTERN_RHS_NO_LIT) + { + parser_emit_cbc_ext_literal (context_p, rhs_opcode, literal_index); + } + else + { + parser_emit_cbc_ext (context_p, rhs_opcode); + } +} /* parser_pattern_emit_rhs */ + +/** + * Form an assignment from a pattern. + */ +static void +parser_pattern_form_assignment (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index, /**< literal index for object pattern */ + parser_line_counter_t ident_line_counter) /**< identifier line counter */ +{ + JERRY_UNUSED (ident_line_counter); + + uint16_t name_index = PARSER_INVALID_LITERAL_INDEX; + + if ((flags & PARSER_PATTERN_BINDING) + || (context_p->last_cbc_opcode == CBC_PUSH_LITERAL && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)) + { + name_index = context_p->lit_object.index; + } + + parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START); + parser_append_binary_single_assignment_token (context_p, flags); + parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index); + + if (context_p->token.type == LEXER_ASSIGN && !(flags & PARSER_PATTERN_REST_ELEMENT)) + { + parser_branch_t skip_init; + lexer_next_token (context_p); + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init); + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (name_index != PARSER_INVALID_LITERAL_INDEX) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + name_index = scanner_save_literal (context_p, name_index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, name_index, 0); + } + } + parser_set_branch_to_current_position (context_p, &skip_init); + } + + parser_process_binary_opcodes (context_p, 0); + + JERRY_ASSERT (context_p->stack_top_uint8 == LEXER_EXPRESSION_START); + parser_stack_pop_uint8 (context_p); + +} /* parser_pattern_form_assignment */ + +/** + * Parse pattern inside a pattern. + */ +static void +parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index) /**< literal index for object pattern */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE); + + parser_pattern_flags_t options = (parser_pattern_flags_t) ((int) PARSER_PATTERN_NESTED_PATTERN | (int) PARSER_PATTERN_TARGET_ON_STACK + | ((int) flags & ((int) PARSER_PATTERN_BINDING | (int) PARSER_PATTERN_LET | (int) PARSER_PATTERN_CONST + | (int) PARSER_PATTERN_LOCAL | (int) PARSER_PATTERN_ARGUMENTS))); + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER + || context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + + if (!(flags & PARSER_PATTERN_REST_ELEMENT)) + { + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_TARGET_DEFAULT); + } + else + { + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + } + else + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_parse_object_initializer (context_p, options); + } + else + { + parser_parse_array_initializer (context_p, options); + } + + parser_emit_cbc (context_p, CBC_POP); +} /* parser_pattern_process_nested_pattern */ + +/** + * Process the current {Binding, Assignment}Property + * + * @return true, if a nested pattern is processed, false otherwise + */ +static bool +parser_pattern_process_assignment (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags, /**< flags */ + uint16_t rhs_opcode, /**< opcode to process the rhs value */ + uint16_t literal_index, /**< literal index for object pattern */ + lexer_token_type_t end_type) /**< end type token */ +{ + if ((context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE) + && (context_p->next_scanner_info_p->source_p != context_p->source_p + || !(context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_NO_DESTRUCTURING))) + { + parser_pattern_process_nested_pattern (context_p, flags, rhs_opcode, literal_index); + return true; + } + + parser_line_counter_t ident_line_counter = context_p->token.line; +#if JERRY_LINE_INFO + parser_line_counter_t ident_column_counter = context_p->token.column; +#endif /* JERRY_LINE_INFO */ + + if (flags & PARSER_PATTERN_BINDING) + { + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + if (flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST) && context_p->token.keyword_type == LEXER_KEYW_LET) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + if (flags & PARSER_PATTERN_ARGUMENTS) + { + if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT) + { + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT; + } +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); +#endif /* JERRY_MODULE_SYSTEM */ + + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + lexer_next_token (context_p); + + if (context_p->token.type != end_type && context_p->token.type != LEXER_ASSIGN + && context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION); + } + } + else + { + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE); + + if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) && !PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + } + + parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter); +#if JERRY_LINE_INFO + parser_line_info_append (context_p, ident_line_counter, ident_column_counter); +#endif /* JERRY_LINE_INFO */ + return false; +} /* parser_pattern_process_assignment */ + +/** + * Parse array initializer. + */ +static void +parser_parse_array_initializer (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags); + + lexer_next_token (context_p); + parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CONTEXT_CREATE); + + while (context_p->token.type != LEXER_RIGHT_SQUARE) + { + uint16_t rhs_opcode = CBC_EXT_ITERATOR_STEP; + + if (context_p->token.type == LEXER_COMMA) + { + parser_emit_cbc_ext (context_p, rhs_opcode); + parser_emit_cbc (context_p, CBC_POP); + lexer_next_token (context_p); + continue; + } + + parser_pattern_flags_t options = flags; + + if (context_p->token.type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + rhs_opcode = CBC_EXT_REST_INITIALIZER; + options = (parser_pattern_flags_t) ((int) options | (int) PARSER_PATTERN_REST_ELEMENT); + } + + parser_pattern_process_assignment (context_p, options, rhs_opcode, PARSER_PATTERN_RHS_NO_LIT, LEXER_RIGHT_SQUARE); + + if (context_p->token.type == LEXER_COMMA && rhs_opcode != CBC_EXT_REST_INITIALIZER) + { + lexer_next_token (context_p); + } + else if (context_p->token.type != LEXER_RIGHT_SQUARE) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + } + + /* close the iterator */ + parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CONTEXT_END); + + parser_pattern_finalize (context_p, flags, &end_pos); +} /* parser_parse_array_initializer */ + +/** + * Parse object initializer. + */ +static void +parser_parse_object_initializer (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags); + + /* 12.14.5.2: ObjectAssignmentPattern : { } */ + if (lexer_check_next_character (context_p, LIT_CHAR_RIGHT_BRACE)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_REQUIRE_OBJECT_COERCIBLE); + lexer_consume_next_character (context_p); + parser_pattern_finalize (context_p, flags, &end_pos); + return; + } + +#ifndef JERRY_NDEBUG + bool rest_found = false; +#endif /* !defined(JERRY_NDEBUG) */ + + cbc_ext_opcode_t context_opcode = CBC_EXT_OBJ_INIT_CONTEXT_CREATE; + + if (flags & PARSER_PATTERN_HAS_REST_ELEMENT) + { + context_opcode = CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE; + } + + parser_emit_cbc_ext (context_p, context_opcode); + + while (true) + { + lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN); + + uint16_t prop_index = context_p->lit_object.index; + parser_line_counter_t start_line = context_p->token.line; + parser_line_counter_t start_column = context_p->token.column; + uint16_t push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL; + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + break; + } + + if (context_p->token.type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_REST_ELEMENT); + + if (parser_pattern_process_assignment (context_p, + flags, + CBC_EXT_OBJ_INIT_PUSH_REST, + PARSER_PATTERN_RHS_NO_LIT, + LEXER_RIGHT_BRACE)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT); + } + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + +#ifndef JERRY_NDEBUG + rest_found = true; +#endif /* !defined(JERRY_NDEBUG) */ + break; + } + + if (context_p->token.type == LEXER_RIGHT_SQUARE) + { + prop_index = PARSER_PATTERN_RHS_NO_LIT; + push_prop_opcode = + ((flags & PARSER_PATTERN_HAS_REST_ELEMENT) ? CBC_EXT_INITIALIZER_PUSH_NAME : CBC_EXT_INITIALIZER_PUSH_PROP); + } + else if (flags & PARSER_PATTERN_HAS_REST_ELEMENT) + { + push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL; + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COLON) + { + lexer_next_token (context_p); + parser_pattern_process_assignment (context_p, flags, push_prop_opcode, prop_index, LEXER_RIGHT_BRACE); + } + else + { + if (push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_NAME || push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_PROP) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + if (context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_ASSIGN + && context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED); + } + + parser_reparse_as_common_identifier (context_p, start_line, start_column); + + if (flags & PARSER_PATTERN_ARGUMENTS) + { + if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT) + { + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT; + } + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); +#endif /* JERRY_MODULE_SYSTEM */ + + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + + lexer_next_token (context_p); + JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE || context_p->token.type == LEXER_ASSIGN + || context_p->token.type == LEXER_COMMA); + + parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line); +#if JERRY_LINE_INFO + parser_line_info_append (context_p, start_line, start_column); +#endif /* JERRY_LINE_INFO */ + } + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + break; + } + else if (context_p->token.type != LEXER_COMMA) + { + parser_raise_error (context_p, PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED); + } + } + + if (flags & PARSER_PATTERN_HAS_REST_ELEMENT) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, + (PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION - PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION)); + } + + parser_emit_cbc_ext (context_p, CBC_EXT_OBJ_INIT_CONTEXT_END); + + parser_pattern_finalize (context_p, flags, &end_pos); + +#ifndef JERRY_NDEBUG + /* Checked at the end because there might be syntax errors before. */ + JERRY_ASSERT (!!(flags & PARSER_PATTERN_HAS_REST_ELEMENT) == rest_found); +#endif /* !defined(JERRY_NDEBUG) */ +} /* parser_parse_object_initializer */ + +/** + * Parse an initializer. + */ +void +parser_parse_initializer (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_parse_object_initializer (context_p, flags); + } + else + { + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_SQUARE); + parser_parse_array_initializer (context_p, flags); + } +} /* parser_parse_initializer */ + +/** + * Parse an initializer using the next character. + */ +void +parser_parse_initializer_by_next_char (parser_context_t *context_p, /**< context */ + parser_pattern_flags_t flags) /**< flags */ +{ + JERRY_ASSERT (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)); + + if (lexer_consume_next_character (context_p) == LIT_CHAR_LEFT_BRACE) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER + || context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + parser_parse_object_initializer (context_p, flags); + } + else + { + parser_parse_array_initializer (context_p, flags); + } +} /* parser_parse_initializer_by_next_char */ + +/** + * Process ternary expression. + */ +static void +parser_process_ternary_expression (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_QUESTION_MARK); + + cbc_opcode_t opcode = CBC_BRANCH_IF_FALSE_FORWARD; + parser_branch_t cond_branch; + parser_branch_t uncond_branch; + + parser_push_result (context_p); + + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_TRUE_FORWARD; + } + + parser_emit_cbc_forward_branch (context_p, (uint16_t) opcode, &cond_branch); + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &uncond_branch); + parser_set_branch_to_current_position (context_p, &cond_branch); + + /* Although byte code is constructed for two branches, + * only one of them will be executed. To reflect this + * the stack is manually adjusted. */ + JERRY_ASSERT (context_p->stack_depth > 0); + context_p->stack_depth--; + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_FOR_CONDITIONAL_EXPECTED); + } + + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + parser_set_branch_to_current_position (context_p, &uncond_branch); + + /* Last opcode rewrite is not allowed because + * the result may come from the first branch. */ + parser_flush_cbc (context_p); + + parser_process_binary_opcodes (context_p, 0); +} /* parser_process_ternary_expression */ + +/** + * Process expression sequence. + */ +static void +parser_process_expression_sequence (parser_context_t *context_p) /**< context */ +{ + if (!CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + parser_emit_cbc (context_p, CBC_POP); + } + + if (context_p->stack_top_uint8 == LEXER_LEFT_PAREN) + { + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL); + + page_p->bytes[context_p->stack.last_position - 1] = LEXER_COMMA_SEP_LIST; + context_p->stack_top_uint8 = LEXER_COMMA_SEP_LIST; + } + + lexer_next_token (context_p); +} /* parser_process_expression_sequence */ + +/** + * Process group expression. + */ +static void +parser_process_group_expression (parser_context_t *context_p, /**< context */ + size_t *grouping_level_p) /**< grouping level */ +{ + JERRY_ASSERT (*grouping_level_p >= PARSER_GROUPING_LEVEL_INCREASE); + (*grouping_level_p) -= PARSER_GROUPING_LEVEL_INCREASE; + + uint8_t token = context_p->stack_top_uint8; + + if (token == LEXER_COMMA_SEP_LIST) + { + parser_push_result (context_p); + parser_flush_cbc (context_p); + } + + parser_stack_pop_uint8 (context_p); + lexer_next_token (context_p); + + /* Lookahead for anonymous function declaration after '=' token when the assignment base is LHS expression + with a single indentifier in it. e.g.: (a) = function () {} */ + if (JERRY_UNLIKELY (context_p->token.type == LEXER_ASSIGN + && PARSER_IS_PUSH_LITERALS_WITH_THIS (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL + && parser_is_assignment_expr (context_p) && *grouping_level_p != PARSE_EXPR_LEFT_HAND_SIDE)) + { + parser_stack_push_uint8 (context_p, LEXER_ASSIGN_GROUP_EXPR); + } +} /* parser_process_group_expression */ + +/** + * Parse block expression. + */ +void +parser_parse_block_expression (parser_context_t *context_p, /**< context */ + int options) /**< option flags */ +{ + parser_parse_expression (context_p, options | PARSE_EXPR_NO_PUSH_RESULT); + + if (CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + JERRY_ASSERT (CBC_SAME_ARGS (context_p->last_cbc_opcode, context_p->last_cbc_opcode + 2)); + PARSER_PLUS_EQUAL_U16 (context_p->last_cbc_opcode, 2); + parser_flush_cbc (context_p); + } + else + { + parser_emit_cbc (context_p, CBC_POP_BLOCK); + } +} /* parser_parse_block_expression */ + +/** + * Parse expression statement. + */ +void +parser_parse_expression_statement (parser_context_t *context_p, /**< context */ + int options) /**< option flags */ +{ + parser_parse_expression (context_p, options | PARSE_EXPR_NO_PUSH_RESULT); + + if (!CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)) + { + parser_emit_cbc (context_p, CBC_POP); + } +} /* parser_parse_expression_statement */ + +JERRY_STATIC_ASSERT ((PARSE_EXPR_LEFT_HAND_SIDE == 0x1), value_of_parse_expr_left_hand_side_must_be_1); + +/** + * Parse expression. + */ +void +parser_parse_expression (parser_context_t *context_p, /**< context */ + int options) /**< option flags */ +{ + size_t grouping_level = (options & PARSE_EXPR_LEFT_HAND_SIDE); + + parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START); + + if (options & PARSE_EXPR_HAS_LITERAL) + { + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + goto process_unary_expression; + } + + while (true) + { + if (parser_parse_unary_expression (context_p, &grouping_level)) + { + parser_process_binary_opcodes (context_p, 0); + break; + } + + while (true) + { +process_unary_expression: + parser_process_unary_expression (context_p, grouping_level); + + if (JERRY_LIKELY (grouping_level != PARSE_EXPR_LEFT_HAND_SIDE)) + { + uint8_t min_prec_treshold = 0; + + if (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type)) + { + if (JERRY_UNLIKELY (context_p->token.type == LEXER_NULLISH_COALESCING)) + { + parser_check_invalid_logical_op (context_p, LEXER_LOGICAL_OR, LEXER_LOGICAL_AND); + } + + min_prec_treshold = parser_binary_precedence_table[context_p->token.type - LEXER_FIRST_BINARY_OP]; + + /* Check for BINARY_LVALUE tokens + LEXER_LOGICAL_OR + LEXER_LOGICAL_AND + LEXER_EXPONENTIATION */ + if ((min_prec_treshold == PARSER_RIGHT_TO_LEFT_ORDER_EXPONENTIATION) + || (min_prec_treshold <= PARSER_RIGHT_TO_LEFT_ORDER_MAX_PRECEDENCE + && min_prec_treshold != PARSER_RIGHT_TO_LEFT_ORDER_TERNARY_PRECEDENCE)) + { + /* Right-to-left evaluation order. */ + min_prec_treshold++; + } + } + + parser_process_binary_opcodes (context_p, min_prec_treshold); + } + if (context_p->token.type == LEXER_RIGHT_PAREN + && (context_p->stack_top_uint8 == LEXER_LEFT_PAREN || context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST)) + { + parser_process_group_expression (context_p, &grouping_level); + continue; + } + + break; + } + + if (grouping_level == PARSE_EXPR_LEFT_HAND_SIDE) + { + break; + } + + if (JERRY_UNLIKELY (context_p->token.type == LEXER_QUESTION_MARK)) + { + parser_process_ternary_expression (context_p); + + if (context_p->token.type == LEXER_RIGHT_PAREN) + { + goto process_unary_expression; + } + } + else if (LEXER_IS_BINARY_OP_TOKEN (context_p->token.type)) + { + parser_append_binary_token (context_p); + lexer_next_token (context_p); + continue; + } + + if (JERRY_UNLIKELY (context_p->token.type == LEXER_COMMA) + && (!(options & PARSE_EXPR_NO_COMMA) || grouping_level >= PARSER_GROUPING_LEVEL_INCREASE)) + { + parser_process_expression_sequence (context_p); + continue; + } + + break; + } + + if (grouping_level >= PARSER_GROUPING_LEVEL_INCREASE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + JERRY_ASSERT (context_p->stack_top_uint8 == LEXER_EXPRESSION_START); + parser_stack_pop_uint8 (context_p); + + if (!(options & PARSE_EXPR_NO_PUSH_RESULT)) + { + parser_push_result (context_p); + } +} /* parser_parse_expression */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-internal.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-internal.h new file mode 100644 index 00000000..14ee21c1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-internal.h @@ -0,0 +1,900 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_PARSER_INTERNAL_H +#define JS_PARSER_INTERNAL_H + +#include "ecma-module.h" + +#include "byte-code.h" +#include "common.h" +#include "js-lexer.h" +#include "js-parser-limits.h" +#include "js-parser.h" +#include "js-scanner.h" +#include "parser-errors.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_internals Internals + * @{ + */ + +/** + * General parser flags. + */ +typedef enum +{ + PARSER_IS_STRICT = (1u << 0), /**< strict mode code */ + PARSER_IS_FUNCTION = (1u << 1), /**< function body is parsed */ + PARSER_IS_CLOSURE = (1u << 2), /**< function body is encapsulated in {} block */ + PARSER_IS_FUNC_EXPRESSION = (1u << 3), /**< a function expression is parsed */ + PARSER_IS_PROPERTY_GETTER = (1u << 4), /**< a property getter function is parsed */ + PARSER_IS_PROPERTY_SETTER = (1u << 5), /**< a property setter function is parsed */ + PARSER_HAS_NON_STRICT_ARG = (1u << 6), /**< the function has arguments which + * are not supported in strict mode */ + PARSER_ARGUMENTS_NEEDED = (1u << 7), /**< arguments object must be created */ + PARSER_LEXICAL_ENV_NEEDED = (1u << 8), /**< lexical environment object must be created */ + PARSER_INSIDE_WITH = (1u << 9), /**< code block is inside a with statement */ + PARSER_NO_END_LABEL = (1u << 10), /**< return instruction must be inserted + * after the last byte code */ + PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 11), /**< pending (unsent) breakpoint + * info is available */ + PARSER_LEXICAL_BLOCK_NEEDED = (1u << 12), /**< global script: needs a lexical environment for let and const + * function: needs a lexical environment for arguments */ + PARSER_IS_ARROW_FUNCTION = (1u << 13), /**< an arrow function is parsed */ + PARSER_IS_GENERATOR_FUNCTION = (1u << 14), /**< a generator function is parsed */ + PARSER_IS_ASYNC_FUNCTION = (1u << 15), /**< an async function is parsed */ + PARSER_DISALLOW_AWAIT_YIELD = (1u << 16), /**< throw SyntaxError for await / yield keywords */ + PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT = (1u << 17), /**< function has complex (ES2015+) argument definition */ + PARSER_FUNCTION_HAS_REST_PARAM = (1u << 18), /**< function has rest parameter */ + PARSER_CLASS_CONSTRUCTOR = (1u << 19), /**< a class constructor is parsed + * Note: PARSER_ALLOW_SUPER must be present */ + /* These five status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ + PARSER_ALLOW_SUPER = (1u << 20), /**< allow super property access */ + PARSER_ALLOW_SUPER_CALL = (1u << 21), /**< allow super constructor call + * Note: PARSER_CLASS_CONSTRUCTOR must be present */ + PARSER_FUNCTION_IS_PARSING_ARGS = (1u << 22), /**< set when parsing function arguments */ + PARSER_INSIDE_CLASS_FIELD = (1u << 23), /**< a class field is being parsed */ + PARSER_ALLOW_NEW_TARGET = (1u << 24), /**< allow new.target parsing in the current context */ + PARSER_IS_METHOD = (1u << 25), /**< method is parsed */ + PARSER_IS_CLASS_STATIC_BLOCK = (1u << 26), /**< a class static block is parsed */ + PARSER_PRIVATE_FUNCTION_NAME = PARSER_IS_FUNC_EXPRESSION, /**< represents private method for + * parser_set_function_name*/ +#if JERRY_MODULE_SYSTEM + PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 27), /**< parsing a function or class default export */ + PARSER_MODULE_STORE_IDENT = (1u << 28), /**< store identifier of the current export statement */ +#endif /* JERRY_MODULE_SYSTEM */ + PARSER_HAS_LATE_LIT_INIT = (1u << 30), /**< there are identifier or string literals which construction + * is postponed after the local parser data is freed */ +#ifndef JERRY_NDEBUG + PARSER_SCANNING_SUCCESSFUL = PARSER_HAS_LATE_LIT_INIT, /**< scanning process was successful */ +#endif /* !JERRY_NDEBUG */ +} parser_general_flags_t; + +/** + * Expression parsing flags. + */ +typedef enum +{ + PARSE_EXPR = 0, /**< parse an expression without any special flags */ + PARSE_EXPR_LEFT_HAND_SIDE = (1u << 0), /**< parse a left-hand-side expression */ + PARSE_EXPR_NO_PUSH_RESULT = (1u << 1), /**< do not push the result of the expression onto the stack */ + PARSE_EXPR_NO_COMMA = (1u << 2), /**< do not parse comma operator */ + PARSE_EXPR_HAS_LITERAL = (1u << 3), /**< a primary literal is provided by a + * CBC_PUSH_LITERAL instruction */ +} parser_expression_flags_t; + +/** + * Pattern parsing flags. + */ +typedef enum +{ + PARSER_PATTERN_NO_OPTS = 0, /**< parse the expression after '=' */ + PARSER_PATTERN_BINDING = (1u << 0), /**< parse BindingPattern */ + PARSER_PATTERN_TARGET_ON_STACK = (1u << 1), /**< assignment target is the topmost element on the stack */ + PARSER_PATTERN_TARGET_DEFAULT = (1u << 2), /**< perform default value comparison for assignment target */ + PARSER_PATTERN_NESTED_PATTERN = (1u << 3), /**< parse pattern inside a pattern */ + PARSER_PATTERN_LET = (1u << 4), /**< pattern is a let declaration */ + PARSER_PATTERN_CONST = (1u << 5), /**< pattern is a const declaration */ + PARSER_PATTERN_LOCAL = (1u << 6), /**< pattern is a local (catch parameter) declaration */ + PARSER_PATTERN_REST_ELEMENT = (1u << 7), /**< parse rest array / object element */ + PARSER_PATTERN_HAS_REST_ELEMENT = (1u << 8), /**< object literal rest element will be present */ + PARSER_PATTERN_ARGUMENTS = (1u << 9), /**< parse arguments binding */ +} parser_pattern_flags_t; + +/** + * Check type for scanner_is_context_needed function. + */ +typedef enum +{ + PARSER_CHECK_BLOCK_CONTEXT, /**< check block context */ + PARSER_CHECK_GLOBAL_CONTEXT, /**< check global context */ + PARSER_CHECK_FUNCTION_CONTEXT, /**< check function context */ +} parser_check_context_type_t; + +/** + * Class field bits. + */ +typedef enum +{ + PARSER_CLASS_FIELD_END = (1u << 0), /**< last class field */ + PARSER_CLASS_FIELD_NORMAL = (1u << 1), /**< normal (non-computed) class field */ + PARSER_CLASS_FIELD_INITIALIZED = (1u << 2), /**< class field is initialized */ + PARSER_CLASS_FIELD_STATIC = (1u << 3), /**< static class field */ + PARSER_CLASS_FIELD_STATIC_BLOCK = (1u << 4), /**< static class field */ +} parser_class_field_type_t; + +/** + * Mask for strict mode code + */ +#define PARSER_STRICT_MODE_MASK 0x1 + +/** + * Shorthand for function closure definition + */ +#define PARSER_FUNCTION_CLOSURE (PARSER_IS_FUNCTION | PARSER_IS_CLOSURE) + +#if PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX +/** + * Maximum number of bytes for branch target. + */ +#define PARSER_MAX_BRANCH_LENGTH 2 +#else /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ +/** + * Maximum number of bytes for branch target. + */ +#define PARSER_MAX_BRANCH_LENGTH 3 +#endif /* PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX */ + +/** + * Offset of PARSER_ALLOW_SUPER + */ +#define PARSER_SAVED_FLAGS_OFFSET JERRY_LOG2 (PARSER_ALLOW_SUPER) + +/** + * Mask of saved flags + */ +#define PARSER_SAVED_FLAGS_MASK \ + ((1 << (JERRY_LOG2 (PARSER_ALLOW_NEW_TARGET) - JERRY_LOG2 (PARSER_ALLOW_SUPER) + 1)) - 1) + +/** + * Get class option bits from parser_general_flags_t + */ +#define PARSER_SAVE_STATUS_FLAGS(opts) ((uint16_t) (((opts) >> PARSER_SAVED_FLAGS_OFFSET) & PARSER_SAVED_FLAGS_MASK)) + +/** + * Mask for get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS_MASK (((ECMA_PARSE_ALLOW_NEW_TARGET << 1) - 1) - (ECMA_PARSE_ALLOW_SUPER - 1)) + +/** + * Shift for get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS_SHIFT (JERRY_LOG2 (PARSER_ALLOW_SUPER) - JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER)) + +/** + * Get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS(opts) \ + (((opts) &PARSER_RESTORE_STATUS_FLAGS_MASK) << PARSER_RESTORE_STATUS_FLAGS_SHIFT) + +/** + * All flags that affect exotic arguments object creation. + */ +#define PARSER_ARGUMENTS_RELATED_FLAGS \ + (PARSER_ARGUMENTS_NEEDED | PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT | PARSER_IS_STRICT) + +/** + * Get the corresponding eval flag for a ecma_parse_opts_t flag + */ +#define PARSER_GET_EVAL_FLAG(type) ((type) >> JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER)) + +/** + * Check non-generator async functions + */ +#define PARSER_IS_NORMAL_ASYNC_FUNCTION(status_flags) \ + (((status_flags) & (PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION)) == PARSER_IS_ASYNC_FUNCTION) + +/* Checks whether unmapped arguments are needed. */ +#define PARSER_NEEDS_MAPPED_ARGUMENTS(status_flags) \ + (((status_flags) &PARSER_ARGUMENTS_RELATED_FLAGS) == PARSER_ARGUMENTS_NEEDED) + +/* The maximum of PARSER_CBC_STREAM_PAGE_SIZE is 127. */ +#define PARSER_CBC_STREAM_PAGE_SIZE ((uint32_t) (64 - sizeof (void *))) + +/* Defines the size of the max page. */ +#define PARSER_STACK_PAGE_SIZE ((uint32_t) (((sizeof (void *) > 4) ? 128 : 64) - sizeof (void *))) + +/* Avoid compiler warnings for += operations. */ +#define PARSER_PLUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) + (value)) +#define PARSER_MINUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) - (value)) +#define PARSER_PLUS_EQUAL_LC(base, value) (base) = (parser_line_counter_t) ((base) + (value)) + +/** + * Argument for a compact-byte code. + */ +typedef struct +{ + uint16_t literal_index; /**< literal index argument */ + uint16_t value; /**< other argument (second literal or byte). */ + uint16_t third_literal_index; /**< literal index argument */ + uint8_t literal_type; /**< last literal type */ + uint8_t literal_keyword_type; /**< last literal keyword type */ +} cbc_argument_t; + +/* Useful parser macros. */ + +#define PARSER_CBC_UNAVAILABLE CBC_EXT_OPCODE + +#define PARSER_TO_EXT_OPCODE(opcode) ((uint16_t) ((opcode) + 256)) +#define PARSER_GET_EXT_OPCODE(opcode) ((opcode) -256) +#define PARSER_IS_BASIC_OPCODE(opcode) ((opcode) < 256) +#define PARSER_IS_PUSH_LITERAL(opcode) \ + ((opcode) == CBC_PUSH_LITERAL || (opcode) == CBC_PUSH_TWO_LITERALS || (opcode) == CBC_PUSH_THREE_LITERALS) +#define PARSER_IS_PUSH_NUMBER(opcode) \ + ((opcode) >= CBC_PUSH_NUMBER_0 && (opcode) <= CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) + +#define PARSER_IS_MUTABLE_PUSH_LITERAL(opcode) ((opcode) >= CBC_PUSH_LITERAL && (opcode) <= CBC_PUSH_THIS_LITERAL) + +#define PARSER_IS_PUSH_LITERALS_WITH_THIS(opcode) ((opcode) >= CBC_PUSH_LITERAL && (opcode) <= CBC_PUSH_THREE_LITERALS) + +#define PARSER_IS_PUSH_PROP(opcode) ((opcode) >= CBC_PUSH_PROP && (opcode) <= CBC_PUSH_PROP_THIS_LITERAL) + +#define PARSER_IS_PUSH_PROP_LITERAL(opcode) \ + ((opcode) >= CBC_PUSH_PROP_LITERAL && (opcode) <= CBC_PUSH_PROP_THIS_LITERAL) + +#define PARSER_PUSH_LITERAL_TO_PUSH_PROP_LITERAL(opcode) \ + (uint16_t) ((opcode) + (CBC_PUSH_PROP_LITERAL - CBC_PUSH_LITERAL)) + +#define PARSER_PUSH_PROP_LITERAL_TO_PUSH_LITERAL(opcode) \ + (uint16_t) ((opcode) - (CBC_PUSH_PROP_LITERAL - CBC_PUSH_LITERAL)) + +#define PARSER_PUSH_PROP_TO_PUSH_PROP_REFERENCE(opcode) \ + (uint16_t) ((opcode) + (CBC_PUSH_PROP_REFERENCE - CBC_PUSH_PROP)) + +#define PARSER_PUSH_PROP_REFERENCE_TO_PUSH_PROP(opcode) \ + (uint16_t) ((opcode) - (CBC_PUSH_PROP_REFERENCE - CBC_PUSH_PROP)) + +#define PARSER_GET_LITERAL(literal_index) \ + ((lexer_literal_t *) parser_list_get (&context_p->literal_pool, (literal_index))) + +#define PARSER_TO_BINARY_OPERATION_WITH_RESULT(opcode) \ + (PARSER_TO_EXT_OPCODE (opcode) - CBC_ASSIGN_ADD + CBC_EXT_ASSIGN_ADD_PUSH_RESULT) + +#define PARSER_TO_BINARY_OPERATION_WITH_BLOCK(opcode) \ + ((uint16_t) (PARSER_TO_EXT_OPCODE (opcode) - CBC_ASSIGN_ADD + CBC_EXT_ASSIGN_ADD_BLOCK)) + +#define PARSER_GET_FLAGS(op) (PARSER_IS_BASIC_OPCODE (op) ? cbc_flags[(op)] : cbc_ext_flags[PARSER_GET_EXT_OPCODE (op)]) + +#define PARSER_OPCODE_IS_RETURN(op) \ + ((op) == CBC_RETURN || (op) == CBC_RETURN_FUNCTION_END || (op) == CBC_RETURN_WITH_LITERAL) + +#define PARSER_ARGS_EQ(op, types) ((PARSER_GET_FLAGS (op) & CBC_ARG_TYPES) == (types)) + +/** + * All data allocated by the parser is + * stored in parser_data_pages in the memory. + */ +#if defined(_WIN32) +#pragma warning(push) +#pragma warning(disable:4200) +#endif +typedef struct parser_mem_page_t +{ + struct parser_mem_page_t *next_p; /**< next page */ + uint8_t bytes[]; /**< memory bytes, C99 flexible array member */ +} parser_mem_page_t; +#if defined(_WIN32) +#pragma warning(pop) +#endif + +/** + * Structure for managing parser memory. + */ +typedef struct +{ + parser_mem_page_t *first_p; /**< first allocated page */ + parser_mem_page_t *last_p; /**< last allocated page */ + uint32_t last_position; /**< position of the last allocated byte */ +} parser_mem_data_t; + +/** + * Parser memory list. + */ +typedef struct +{ + parser_mem_data_t data; /**< storage space */ + uint32_t page_size; /**< size of each page */ + uint32_t item_size; /**< size of each item */ + uint32_t item_count; /**< number of items on each page */ +} parser_list_t; + +/** + * Iterator for parser memory list. + */ +typedef struct +{ + parser_list_t *list_p; /**< parser list */ + parser_mem_page_t *current_p; /**< currently processed page */ + size_t current_position; /**< current position on the page */ +} parser_list_iterator_t; + +/** + * Parser memory stack. + */ +typedef struct +{ + parser_mem_data_t data; /**< storage space */ + parser_mem_page_t *free_page_p; /**< space for fast allocation */ +} parser_stack_t; + +/** + * Iterator for parser memory stack. + */ +typedef struct +{ + parser_mem_page_t *current_p; /**< currently processed page */ + size_t current_position; /**< current position on the page */ +} parser_stack_iterator_t; + +/** + * Branch type. + */ +typedef struct +{ + parser_mem_page_t *page_p; /**< branch location page */ + uint32_t offset; /**< branch location offset */ +} parser_branch_t; + +/** + * Branch chain type. + */ +typedef struct parser_branch_node_t +{ + struct parser_branch_node_t *next_p; /**< next linked list node */ + parser_branch_t branch; /**< branch */ +} parser_branch_node_t; + +/** + * Items of scope stack. + */ +typedef struct +{ + uint16_t map_from; /**< original literal index */ + uint16_t map_to; /**< encoded register or literal index and flags */ +} parser_scope_stack_t; + +/** + * This item represents a function literal in the scope stack. + * + * When map_from == PARSER_SCOPE_STACK_FUNC: + * map_to represents the literal reserved for a function literal + * Note: the name of the function is the previous value in the scope stack + * Note: map_to is not encoded in this case + */ +#define PARSER_SCOPE_STACK_FUNC 0xffff + +/** + * Mask for decoding the register index of map_to + */ +#define PARSER_SCOPE_STACK_REGISTER_MASK 0x3fff + +/** + * Function statements with the name specified + * in map_from should not be copied to global scope. + */ +#define PARSER_SCOPE_STACK_NO_FUNCTION_COPY 0x8000 + +/** + * The scope stack item represents a const binding stored in register + */ +#define PARSER_SCOPE_STACK_IS_CONST_REG 0x4000 + +/** + * The scope stack item represents a binding which has already created with ECMA_VALUE_UNINITIALIZED + */ +#define PARSER_SCOPE_STACK_IS_LOCAL_CREATED (PARSER_SCOPE_STACK_IS_CONST_REG) + +/** + * Starting literal index for registers. + */ +#define PARSER_REGISTER_START 0x8000 + +/** + * Invalid literal index + */ +#define PARSER_INVALID_LITERAL_INDEX UINT16_MAX + +/** + * Lastly emitted opcode is not a function literal + */ +#define PARSER_NOT_FUNCTION_LITERAL PARSER_INVALID_LITERAL_INDEX + +/** + * Lastly emitted opcode is not a named function literal + */ +#define PARSER_NAMED_FUNCTION (uint16_t) (PARSER_NOT_FUNCTION_LITERAL - 1) + +/** + * Lastly emitted opcode is not an anonymous class literal + */ +#define PARSER_ANONYMOUS_CLASS (uint16_t) (PARSER_NAMED_FUNCTION - 1) + +/* Forward definitions for js-scanner-internal.h. */ +struct scanner_context_t; +typedef struct scanner_context_t scanner_context_t; + +#if JERRY_LINE_INFO + +typedef struct +{ + parser_mem_page_t *last_page_p; /**< last page of line info data */ + uint32_t byte_code_position; /**< last byte code position */ + parser_line_counter_t line; /**< last line */ + parser_line_counter_t column; /**< last column */ +} parser_line_info_data_t; + +#endif /* JERRY_LINE_INFO */ + +/** + * List of private field contexts + */ +typedef struct parser_private_context_t +{ + scanner_class_private_member_t *members_p; /**< current private field context members */ + struct parser_private_context_t *prev_p; /**< previous private field context */ + uint8_t opts; /**< options */ +} parser_private_context_t; + +/** + * Those members of a context which needs + * to be saved when a sub-function is parsed. + */ +typedef struct parser_saved_context_t +{ + /* Parser members. */ + uint32_t status_flags; /**< parsing options */ + uint16_t stack_depth; /**< current stack depth */ + uint16_t stack_limit; /**< maximum stack depth */ + struct parser_saved_context_t *prev_context_p; /**< last saved context */ + parser_stack_iterator_t last_statement; /**< last statement position */ + + /* Literal types */ + uint16_t argument_count; /**< number of function arguments */ + uint16_t argument_length; /**< length property of arguments */ + uint16_t register_count; /**< number of registers */ + uint16_t literal_count; /**< number of literals */ + + /* Memory storage members. */ + parser_mem_data_t byte_code; /**< byte code buffer */ + uint32_t byte_code_size; /**< byte code size for branches */ + parser_mem_data_t literal_pool_data; /**< literal list */ + parser_scope_stack_t *scope_stack_p; /**< scope stack */ + uint16_t scope_stack_size; /**< size of scope stack */ + uint16_t scope_stack_top; /**< preserved top of scope stack */ + uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */ + uint16_t scope_stack_global_end; /**< end of global declarations of a function */ + ecma_value_t tagged_template_literal_cp; /**< compessed pointer to the tagged template literal collection */ +#ifndef JERRY_NDEBUG + uint16_t context_stack_depth; /**< current context stack depth */ +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + parser_line_info_data_t *line_info_p; /**< line info data */ +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + const uint8_t *function_start_p; /**< start position of the current function */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} parser_saved_context_t; + +/** + * Shared parser context. + */ +typedef struct +{ + PARSER_TRY_CONTEXT (try_buffer); /**< try_buffer */ + parser_error_msg_t error; /**< error code */ + /** Union for rarely used members. */ + union + { + void *allocated_buffer_p; /**< dinamically allocated buffer + * which needs to be freed on error */ + scanner_context_t *scanner_context_p; /**< scanner context for the pre-scanner */ + } u; + uint32_t allocated_buffer_size; /**< size of the dinamically allocated buffer */ + + /* Parser members. */ + uint32_t status_flags; /**< status flags */ + uint32_t global_status_flags; /**< global status flags */ + uint16_t stack_depth; /**< current stack depth */ + uint16_t stack_limit; /**< maximum stack depth */ + const jerry_parse_options_t *options_p; /**< parse options */ + parser_saved_context_t *last_context_p; /**< last saved context */ + parser_stack_iterator_t last_statement; /**< last statement position */ + cbc_script_t *script_p; /**< current script */ + const uint8_t *source_start_p; /**< source start */ + lit_utf8_size_t source_size; /**< source size */ + const uint8_t *arguments_start_p; /**< function argument list start */ + lit_utf8_size_t arguments_size; /**< function argument list size */ + ecma_value_t script_value; /**< current script as value */ + ecma_value_t argument_list; /**< current argument list as value */ + ecma_value_t user_value; /**< current user value */ + +#if JERRY_MODULE_SYSTEM + ecma_module_names_t *module_names_p; /**< import / export names that is being processed */ + lexer_literal_t *module_identifier_lit_p; /**< the literal for the identifier of the current element */ +#endif /* JERRY_MODULE_SYSTEM */ + + /* Lexer members. */ + lexer_token_t token; /**< current token */ + lexer_lit_object_t lit_object; /**< current literal object */ + const uint8_t *source_p; /**< next source byte */ + const uint8_t *source_end_p; /**< last source byte */ + parser_line_counter_t line; /**< current line */ + parser_line_counter_t column; /**< current column */ + + /* Scanner members. */ + scanner_info_t *next_scanner_info_p; /**< next scanner info block */ + scanner_info_t *active_scanner_info_p; /**< currently active scanner info block */ + scanner_info_t *skipped_scanner_info_p; /**< next scanner info block */ + scanner_info_t *skipped_scanner_info_end_p; /**< currently active scanner info block */ + + /* Compact byte code members. */ + cbc_argument_t last_cbc; /**< argument of the last cbc */ + uint16_t last_cbc_opcode; /**< opcode of the last cbc */ + + /* Literal types */ + uint16_t argument_count; /**< number of function arguments */ + uint16_t argument_length; /**< length property of arguments */ + uint16_t register_count; /**< number of registers */ + uint16_t literal_count; /**< number of literals */ + + /* Memory storage members. */ + parser_mem_data_t byte_code; /**< byte code buffer */ + uint32_t byte_code_size; /**< current byte code size for branches */ + parser_list_t literal_pool; /**< literal list */ + parser_mem_data_t stack; /**< storage space */ + parser_scope_stack_t *scope_stack_p; /**< scope stack */ + parser_mem_page_t *free_page_p; /**< space for fast allocation */ + uint16_t scope_stack_size; /**< size of scope stack */ + uint16_t scope_stack_top; /**< current top of scope stack */ + uint16_t scope_stack_reg_top; /**< current top register of scope stack */ + uint16_t scope_stack_global_end; /**< end of global declarations of a function */ + ecma_value_t tagged_template_literal_cp; /**< compessed pointer to the tagged template literal collection */ + parser_private_context_t *private_context_p; /**< private context */ + uint8_t stack_top_uint8; /**< top byte stored on the stack */ + +#ifndef JERRY_NDEBUG + /* Variables for debugging / logging. */ + uint16_t context_stack_depth; /**< current context stack depth */ +#endif /* !JERRY_NDEBUG */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + int is_show_opcodes; /**< show opcodes */ + uint32_t total_byte_code_size; /**< total byte code size */ +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +#if JERRY_LINE_INFO + parser_line_info_data_t *line_info_p; /**< line info data */ +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + const uint8_t *function_start_p; /**< start position of the function which will be parsed */ + const uint8_t *function_end_p; /**< end position of the current function */ +#endif /* JERRY_FUNCTION_TO_STRING */ +} parser_context_t; + +/** + * @} + * @} + * @} + * + * \addtogroup mem Memory allocation + * @{ + * + * \addtogroup mem_parser Parser memory manager + * @{ + */ + +/* Memory management. + * Note: throws an error if unsuccessful. */ +void *parser_malloc (parser_context_t *context_p, size_t size); +void parser_free (void *ptr, size_t size); +void *parser_malloc_local (parser_context_t *context_p, size_t size); +void parser_free_local (void *ptr, size_t size); +void parser_free_allocated_buffer (parser_context_t *context_p); + +/* Parser byte stream. */ + +void parser_cbc_stream_init (parser_mem_data_t *data_p); +void parser_cbc_stream_free (parser_mem_data_t *data_p); +void parser_cbc_stream_alloc_page (parser_context_t *context_p, parser_mem_data_t *data_p); + +/* Parser list. Ensures pointer alignment. */ + +void parser_list_init (parser_list_t *list_p, uint32_t item_size, uint32_t item_count); +void parser_list_free (parser_list_t *list_p); +void parser_list_reset (parser_list_t *list_p); +void *parser_list_append (parser_context_t *context_p, parser_list_t *list_p); +void *parser_list_get (parser_list_t *list_p, size_t index); +void parser_list_iterator_init (parser_list_t *list_p, parser_list_iterator_t *iterator_p); +void *parser_list_iterator_next (parser_list_iterator_t *iterator_p); + +/* Parser stack. Optimized for pushing bytes. + * Pop functions never throws error. */ + +void parser_stack_init (parser_context_t *context_p); +void parser_stack_free (parser_context_t *context_p); +void parser_stack_push_uint8 (parser_context_t *context_p, uint8_t uint8_value); +void parser_stack_pop_uint8 (parser_context_t *context_p); +void parser_stack_change_last_uint8 (parser_context_t *context_p, uint8_t new_value); +uint8_t *parser_stack_get_prev_uint8 (parser_context_t *context_p); +void parser_stack_push_uint16 (parser_context_t *context_p, uint16_t uint16_value); +uint16_t parser_stack_pop_uint16 (parser_context_t *context_p); +void parser_stack_push (parser_context_t *context_p, const void *data_p, uint32_t length); +void parser_stack_pop (parser_context_t *context_p, void *data_p, uint32_t length); +void parser_stack_iterator_init (parser_context_t *context_p, parser_stack_iterator_t *iterator); +uint8_t parser_stack_iterator_read_uint8 (parser_stack_iterator_t *iterator); +void parser_stack_iterator_skip (parser_stack_iterator_t *iterator, size_t length); +void parser_stack_iterator_read (parser_stack_iterator_t *iterator, void *data_p, size_t length); +void parser_stack_iterator_write (parser_stack_iterator_t *iterator, const void *data_p, size_t length); + +/** + * @} + * @} + * + * \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +/* Compact byte code emitting functions. */ + +void parser_flush_cbc (parser_context_t *context_p); +void parser_emit_cbc (parser_context_t *context_p, uint16_t opcode); +void parser_emit_cbc_literal (parser_context_t *context_p, uint16_t opcode, uint16_t literal_index); +void +parser_emit_cbc_literal_value (parser_context_t *context_p, uint16_t opcode, uint16_t literal_index, uint16_t value); +void parser_emit_cbc_literal_from_token (parser_context_t *context_p, uint16_t opcode); +void parser_emit_cbc_call (parser_context_t *context_p, uint16_t opcode, size_t call_arguments); +void parser_emit_cbc_push_number (parser_context_t *context_p, bool is_negative_number); +void parser_emit_cbc_forward_branch (parser_context_t *context_p, uint16_t opcode, parser_branch_t *branch_p); +parser_branch_node_t * +parser_emit_cbc_forward_branch_item (parser_context_t *context_p, uint16_t opcode, parser_branch_node_t *next_p); +void parser_emit_cbc_backward_branch (parser_context_t *context_p, uint16_t opcode, uint32_t offset); +ecma_string_t *parser_new_ecma_string_from_literal (lexer_literal_t *literal_p); +void parser_set_branch_to_current_position (parser_context_t *context_p, parser_branch_t *branch_p); +void parser_set_breaks_to_current_position (parser_context_t *context_p, parser_branch_node_t *current_p); +void parser_set_continues_to_current_position (parser_context_t *context_p, parser_branch_node_t *current_p); +void parser_reverse_class_fields (parser_context_t *context_p, size_t fields_size); + +/* Convenience macros. */ +#define parser_emit_cbc_ext(context_p, opcode) parser_emit_cbc ((context_p), PARSER_TO_EXT_OPCODE (opcode)) +#define parser_emit_cbc_ext_literal(context_p, opcode, literal_index) \ + parser_emit_cbc_literal ((context_p), PARSER_TO_EXT_OPCODE (opcode), (literal_index)) +#define parser_emit_cbc_ext_literal_from_token(context_p, opcode) \ + parser_emit_cbc_literal_from_token ((context_p), PARSER_TO_EXT_OPCODE (opcode)) +#define parser_emit_cbc_ext_call(context_p, opcode, call_arguments) \ + parser_emit_cbc_call ((context_p), PARSER_TO_EXT_OPCODE (opcode), (call_arguments)) +#define parser_emit_cbc_ext_call(context_p, opcode, call_arguments) \ + parser_emit_cbc_call ((context_p), PARSER_TO_EXT_OPCODE (opcode), (call_arguments)) +#define parser_emit_cbc_ext_forward_branch(context_p, opcode, branch_p) \ + parser_emit_cbc_forward_branch ((context_p), PARSER_TO_EXT_OPCODE (opcode), (branch_p)) +#define parser_emit_cbc_ext_backward_branch(context_p, opcode, offset) \ + parser_emit_cbc_backward_branch ((context_p), PARSER_TO_EXT_OPCODE (opcode), (offset)) + +/** + * @} + * + * \addtogroup jsparser_lexer Lexer + * @{ + */ + +/* Lexer functions */ + +void lexer_next_token (parser_context_t *context_p); +bool lexer_check_next_character (parser_context_t *context_p, lit_utf8_byte_t character); +bool lexer_check_next_characters (parser_context_t *context_p, lit_utf8_byte_t character1, lit_utf8_byte_t character2); +uint8_t lexer_consume_next_character (parser_context_t *context_p); +bool lexer_check_post_primary_exp (parser_context_t *context_p); +void lexer_skip_empty_statements (parser_context_t *context_p); +bool lexer_check_arrow (parser_context_t *context_p); +bool lexer_check_arrow_param (parser_context_t *context_p); +bool lexer_check_yield_no_arg (parser_context_t *context_p); +bool lexer_consume_generator (parser_context_t *context_p); +bool lexer_consume_assign (parser_context_t *context_p); +void lexer_update_await_yield (parser_context_t *context_p, uint32_t status_flags); +bool lexer_scan_private_identifier (parser_context_t *context_p); +void lexer_parse_string (parser_context_t *context_p, lexer_string_options_t opts); +void lexer_expect_identifier (parser_context_t *context_p, uint8_t literal_type); +bool lexer_scan_identifier (parser_context_t *context_p, lexer_parse_options_t opts); +void lexer_check_property_modifier (parser_context_t *context_p); +void lexer_convert_ident_to_cesu8 (uint8_t *destination_p, const uint8_t *source_p, prop_length_t length); + +const uint8_t *lexer_convert_literal_to_chars (parser_context_t *context_p, + const lexer_lit_location_t *literal_p, + uint8_t *local_byte_array_p, + lexer_string_options_t opts); +void lexer_expect_object_literal_id (parser_context_t *context_p, uint32_t ident_opts); +lexer_literal_t *lexer_construct_unused_literal (parser_context_t *context_p); +void lexer_construct_literal_object (parser_context_t *context_p, + const lexer_lit_location_t *lit_location_p, + uint8_t literal_type); +bool lexer_construct_number_object (parser_context_t *context_p, bool is_expr, bool is_negative_number); +void lexer_convert_push_number_to_push_literal (parser_context_t *context_p); +uint16_t lexer_construct_function_object (parser_context_t *context_p, uint32_t extra_status_flags); +uint16_t lexer_construct_class_static_block_function (parser_context_t *context_p); +void lexer_construct_regexp_object (parser_context_t *context_p, bool parse_only); +bool lexer_compare_identifier_to_string (const lexer_lit_location_t *left_p, const uint8_t *right_p, size_t size); +bool lexer_compare_identifiers (parser_context_t *context_p, + const lexer_lit_location_t *left_p, + const lexer_lit_location_t *right_p); +bool lexer_current_is_literal (parser_context_t *context_p, const lexer_lit_location_t *right_ident_p); +bool lexer_string_is_use_strict (parser_context_t *context_p); +bool lexer_string_is_directive (parser_context_t *context_p); +bool lexer_token_is_identifier (parser_context_t *context_p, const char *identifier_p, size_t identifier_length); +bool lexer_token_is_let (parser_context_t *context_p); +bool lexer_token_is_async (parser_context_t *context_p); +bool lexer_compare_literal_to_string (parser_context_t *context_p, const char *string_p, size_t string_length); +void lexer_init_line_info (parser_context_t *context_p); +uint8_t lexer_convert_binary_lvalue_token_to_binary (uint8_t token); + +/** + * @} + * + * \addtogroup jsparser_expr Expression parser + * @{ + */ + +/* Parser functions. */ + +void parser_parse_block_expression (parser_context_t *context_p, int options); +void parser_parse_expression_statement (parser_context_t *context_p, int options); +void parser_parse_expression (parser_context_t *context_p, int options); +void parser_resolve_private_identifier (parser_context_t *context_p); +void parser_save_private_context (parser_context_t *context_p, + parser_private_context_t *private_ctx_p, + scanner_class_info_t *class_info_p); +void parser_restore_private_context (parser_context_t *context_p, parser_private_context_t *private_ctx_p); +void parser_parse_class (parser_context_t *context_p, bool is_statement); +void parser_parse_initializer (parser_context_t *context_p, parser_pattern_flags_t flags); +void parser_parse_initializer_by_next_char (parser_context_t *context_p, parser_pattern_flags_t flags); +/** + * @} + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +void scanner_release_next (parser_context_t *context_p, size_t size); +void scanner_set_active (parser_context_t *context_p); +void scanner_revert_active (parser_context_t *context_p); +void scanner_release_active (parser_context_t *context_p, size_t size); +void scanner_release_switch_cases (scanner_case_info_t *case_p); +void scanner_release_private_fields (scanner_class_private_member_t *member_p); +void scanner_seek (parser_context_t *context_p); +void scanner_reverse_info_list (parser_context_t *context_p); +void scanner_cleanup (parser_context_t *context_p); + +bool scanner_is_context_needed (parser_context_t *context_p, parser_check_context_type_t check_type); +bool scanner_try_scan_new_target (parser_context_t *context_p); +void scanner_check_variables (parser_context_t *context_p); +void scanner_create_variables (parser_context_t *context_p, uint32_t option_flags); + +void scanner_get_location (scanner_location_t *location_p, parser_context_t *context_p); +void scanner_set_location (parser_context_t *context_p, scanner_location_t *location_p); +uint16_t scanner_decode_map_to (parser_scope_stack_t *stack_item_p); +uint16_t scanner_save_literal (parser_context_t *context_p, uint16_t ident_index); +bool scanner_literal_is_const_reg (parser_context_t *context_p, uint16_t literal_index); +bool scanner_literal_is_created (parser_context_t *context_p, uint16_t literal_index); +bool scanner_literal_exists (parser_context_t *context_p, uint16_t literal_index); + +void scanner_scan_all (parser_context_t *context_p); + +/** + * @} + * + * \addtogroup jsparser_stmt Statement parser + * @{ + */ + +void parser_parse_statements (parser_context_t *context_p); +void parser_free_jumps (parser_stack_iterator_t iterator); + +#if JERRY_MODULE_SYSTEM +/** + * @} + * + * \addtogroup jsparser_stmt Module statement parser + * @{ + */ + +extern const lexer_lit_location_t lexer_default_literal; +void parser_module_check_request_place (parser_context_t *context_p); +void parser_module_context_init (parser_context_t *context_p); +void parser_module_append_names (parser_context_t *context_p, ecma_module_names_t **module_names_p); +void parser_module_handle_module_specifier (parser_context_t *context_p, ecma_module_node_t **node_list_p); +void parser_module_handle_requests (parser_context_t *context_p); +void parser_module_parse_export_clause (parser_context_t *context_p); +void parser_module_parse_import_clause (parser_context_t *context_p); +void parser_module_set_default (parser_context_t *context_p); +bool parser_module_check_duplicate_import (parser_context_t *context_p, ecma_string_t *local_name_p); +bool parser_module_check_duplicate_export (parser_context_t *context_p, ecma_string_t *export_name_p); +void parser_module_append_export_name (parser_context_t *context_p); +void +parser_module_add_names_to_node (parser_context_t *context_p, ecma_string_t *imex_name_p, ecma_string_t *local_name_p); + +#endif /* JERRY_MODULE_SYSTEM */ + +/* + * @} + * + * \addtogroup jsparser_line_info_create Create line info data + * @{ + */ + +#if JERRY_LINE_INFO +void parser_line_info_free (parser_line_info_data_t *line_info_p); +void parser_line_info_append (parser_context_t *context_p, parser_line_counter_t line, parser_line_counter_t column); +uint8_t *parser_line_info_generate (parser_context_t *context_p); +#endif /* JERRY_LINE_INFO */ + +/** + * @} + * + * \addtogroup jsparser_parser Parser + * @{ + */ + +ecma_compiled_code_t *parser_parse_function (parser_context_t *context_p, uint32_t status_flags); +ecma_compiled_code_t *parser_parse_class_static_block (parser_context_t *context_p); +ecma_compiled_code_t *parser_parse_arrow_function (parser_context_t *context_p, uint32_t status_flags); +ecma_compiled_code_t *parser_parse_class_fields (parser_context_t *context_p); +void parser_set_function_name (parser_context_t *context_p, + uint16_t function_literal_index, + uint16_t name_index, + uint32_t status_flags); +void parser_compiled_code_set_function_name (parser_context_t *context_p, + ecma_compiled_code_t *bytecode_p, + uint16_t name_index, + uint32_t status_flags); +uint16_t parser_check_anonymous_function_declaration (parser_context_t *context_p); + +/* Error management. */ + +void parser_raise_error (parser_context_t *context_p, parser_error_msg_t error); + +#if JERRY_PARSER_DUMP_BYTE_CODE +void util_print_cbc (ecma_compiled_code_t *compiled_code_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_PARSER_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-limits.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-limits.h new file mode 100644 index 00000000..0eb9b538 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-limits.h @@ -0,0 +1,134 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_PARSER_LIMITS_H +#define JS_PARSER_LIMITS_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_internals Internals + * @{ + */ + +/** + * Maximum identifier length accepted by the parser. + * Limit: LEXER_MAX_STRING_LENGTH. + */ +#ifndef PARSER_MAXIMUM_IDENT_LENGTH +#define PARSER_MAXIMUM_IDENT_LENGTH 255 +#endif /* !PARSER_MAXIMUM_IDENT_LENGTH */ + +/** + * Maximum string limit. + * Limit: 2147483647 / 65535. + */ +#if JERRY_CPOINTER_32_BIT +#define PARSER_MAXIMUM_STRING_LIMIT 2147483647 +#else /* !JERRY_CPOINTER_32_BIT */ +#define PARSER_MAXIMUM_STRING_LIMIT 65535 +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Maximum string length. + * Limit: PARSER_MAXIMUM_STRING_LIMIT. + */ +#ifndef PARSER_MAXIMUM_STRING_LENGTH +#define PARSER_MAXIMUM_STRING_LENGTH PARSER_MAXIMUM_STRING_LIMIT +#endif /* !PARSER_MAXIMUM_STRING_LENGTH */ + +/** + * Maximum number of registers. + * Limit: min: 256, max: min(PARSER_MAXIMUM_NUMBER_OF_LITERALS / 2, 16383) + */ +#ifndef PARSER_MAXIMUM_NUMBER_OF_REGISTERS +#define PARSER_MAXIMUM_NUMBER_OF_REGISTERS 256 +#endif /* !PARSER_MAXIMUM_NUMBER_OF_REGISTERS */ + +/** + * Maximum number of literals. + * Limit: 32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS. Recommended: 32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS. + */ +#ifndef PARSER_MAXIMUM_NUMBER_OF_LITERALS +#define PARSER_MAXIMUM_NUMBER_OF_LITERALS (32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS) +#endif /* !PARSER_MAXIMUM_NUMBER_OF_LITERALS */ + +/** + * Maximum depth of scope stack. + * Limit: 32767. Recommended: 32767 + */ +#ifndef PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK +#define PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK 32767 +#endif /* !PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK */ + +/** + * Maximum code size. + * Limit: 16777215. Recommended: 65535, 16777215. + */ +#ifndef PARSER_MAXIMUM_CODE_SIZE +#define PARSER_MAXIMUM_CODE_SIZE (65535 << (JMEM_ALIGNMENT_LOG)) +#endif /* !PARSER_MAXIMUM_CODE_SIZE */ + +/** + * Maximum number of values pushed onto the stack by a function. + * Limit: 65500. Recommended: 1024. + */ +#ifndef PARSER_MAXIMUM_STACK_LIMIT +#define PARSER_MAXIMUM_STACK_LIMIT 1024 + +#endif /* !PARSER_MAXIMUM_STACK_LIMIT */ + +/* Checks. */ + +#if (PARSER_MAXIMUM_STRING_LENGTH < 1) || (PARSER_MAXIMUM_STRING_LENGTH > PARSER_MAXIMUM_STRING_LIMIT) +#error "Maximum string length is not within range." +#endif /* (PARSER_MAXIMUM_STRING_LENGTH < 1) || (PARSER_MAXIMUM_STRING_LENGTH > PARSER_MAXIMUM_STRING_LIMIT) */ + +#if (PARSER_MAXIMUM_IDENT_LENGTH < 1) || (PARSER_MAXIMUM_IDENT_LENGTH > PARSER_MAXIMUM_STRING_LENGTH) +#error "Maximum identifier length is not within range." +#endif /* (PARSER_MAXIMUM_IDENT_LENGTH < 1) || (PARSER_MAXIMUM_IDENT_LENGTH > PARSER_MAXIMUM_STRING_LENGTH) */ + +#if ((PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) \ + || (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS > 32767)) +#error "Maximum number of literals is not within range." +#endif /* ((PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) \ + || (PARSER_MAXIMUM_NUMBER_OF_LITERALS > 32767)) */ + +#if (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK < 1) || (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK > 32767) +#error "Maximum depth of scope stack is not within range." +#endif /* (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK < 1) || (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK > 32767) */ + +#if ((PARSER_MAXIMUM_NUMBER_OF_REGISTERS * 2) > PARSER_MAXIMUM_NUMBER_OF_LITERALS) +#error "Maximum number of registers is not within range." +#endif /* ((PARSER_MAXIMUM_NUMBER_OF_REGISTERS * 2) > PARSER_MAXIMUM_NUMBER_OF_LITERALS) */ + +#if (PARSER_MAXIMUM_CODE_SIZE < 4096) || (PARSER_MAXIMUM_CODE_SIZE > 16777215) +#error "Maximum code size is not within range." +#endif /* (PARSER_MAXIMUM_CODE_SIZE < 4096) || (PARSER_MAXIMUM_CODE_SIZE > 16777215) */ + +#if (PARSER_MAXIMUM_STACK_LIMIT < 16) || (PARSER_MAXIMUM_STACK_LIMIT > 65500) +#error "Maximum function stack usage is not within range." +#endif /* (PARSER_MAXIMUM_STACK_LIMIT < 16) || (PARSER_MAXIMUM_STACK_LIMIT > 65500) */ + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_PARSER_LIMITS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-line-info-create.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-line-info-create.cpp new file mode 100644 index 00000000..475d6b4f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-line-info-create.cpp @@ -0,0 +1,592 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-line-info.h" + +#include "js-parser-internal.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_line_info_create Create line info data + * @{ + */ + +#if JERRY_PARSER + +#if JERRY_LINE_INFO + +/* + * The line-info data structure uses two number encodings: + * + * Vlq (variable length quantity): + * Each byte has 7 bit data and the highest bit is set for continuation. + * The format is big endian. + * + * Small: + * One byte can encode signed values between 127 and -126. + * Two byte can encode signed values between 319 and -318. + * Large values are encoded with vlq with a prefix byte. + * + * The line-info data structure is a sequence of chunks: + * + * +------+--------------+------------+----------------+ + * | Line | StreamLength | StreamData | [ByteCodeSize] | + * +------+--------------+------------+----------------+ + * + * Line [Vlq encoding]: + * Specifies the start line of this chunk, relative to its previous value. + * The starting column is always ECMA_LINE_INFO_COLUMN_DEFAULT + * + * StreamLength [uint8_t]: + * Length of the StreamData in bytes minus ECMA_LINE_INFO_STREAM_SIZE_MIN. + * The 0 value represents the last chunk, which size is not specified + * (Can be less than ECMA_LINE_INFO_STREAM_SIZE_MIN). + * + * StreamData [sequence of bytes]: + * Sequence of the following items: + * + * +-----------+--------+--------+ + * | EndOffset | [Line] | Column | + * +-----------+--------+--------+ + * + * EndOffset [Small encoding]: + * Specifies the EndOffset in the byte code, relative to the previous EndOffset. + * The range of byte codes corresponding to the line/column position of this item + * is between the EndOffset of the previous item (inclusive) and the EndOffset + * of this item (exclusive). The last end offset of a stream is always 0, which + * represents an unterminated range. + * + * Line [Small encoding] [Optional]: + * If bit 1 of end offset is set, this specifies the line position of this item, + * relative to the previous line position, and the column position is set to + * ECMA_LINE_INFO_COLUMN_DEFAULT. + * + * Column [Small encoding]: + * Specifies the current column position relative to the previous column position. + * + * ByteCodeSize [Vlq encoding] [Optional]: + * If StreamLength is not 0, this specifies the byte code size of the whole range. + * This value can be used to skip the byte codes which line info is stored + * in this chunk. This information is not available for the last chunk. + */ + +/** + * Maximum number of bytes requires to encode a number. + */ +#define PARSER_LINE_INFO_BUFFER_MAX_SIZE 6 + +/** + * Stream generation ends after this size is reached, + * since there might be not enough place for the next item. + */ +#define PARSER_LINE_INFO_STREAM_SIZE_LIMIT \ + (ECMA_LINE_INFO_STREAM_SIZE_MIN + UINT8_MAX - ((2 * PARSER_LINE_INFO_BUFFER_MAX_SIZE) + 1)) + +/** + * Page size of line info pages excluding the first one. + */ +#define PARSER_LINE_INFO_PAGE_SIZE (sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE) + +/** + * Page size of the first line info page. + */ +#define PARSER_LINE_INFO_FIRST_PAGE_SIZE (sizeof (parser_line_info_data_t) + PARSER_LINE_INFO_PAGE_SIZE) + +/** + * Get memory data of the first page. + */ +#define PARSER_LINE_INFO_GET_FIRST_PAGE(line_info_p) (((parser_mem_page_t *) ((line_info_p) + 1))) + +/** + * Free line info temporary data collected during parsing. + */ +void +parser_line_info_free (parser_line_info_data_t *line_info_p) +{ + if (line_info_p == NULL) + { + return; + } + + parser_mem_page_t *current_page_p = PARSER_LINE_INFO_GET_FIRST_PAGE (line_info_p)->next_p; + parser_free (line_info_p, PARSER_LINE_INFO_FIRST_PAGE_SIZE); + + while (current_page_p != NULL) + { + parser_mem_page_t *next_p = current_page_p->next_p; + + parser_free (current_page_p, PARSER_LINE_INFO_PAGE_SIZE); + current_page_p = next_p; + } +} /* parser_line_info_free */ + +/** + * Encodes an uint32_t number into a buffer. Numbers expected to be larger values. + * + * @return the number of bytes written to the buffer + */ +static uint32_t +parser_line_info_encode_vlq (uint8_t *buffer_p, /**< target buffer */ + uint32_t value) /**< encoded value */ +{ + if (value <= ECMA_LINE_INFO_VLQ_MASK) + { + *buffer_p = (uint8_t) value; + return 1; + } + + uint32_t length = 0; + uint32_t current_value = value; + + do + { + current_value >>= ECMA_LINE_INFO_VLQ_SHIFT; + length++; + } while (current_value > 0); + + buffer_p += length; + + do + { + *(--buffer_p) = (uint8_t) (value | ECMA_LINE_INFO_VLQ_CONTINUE); + value >>= ECMA_LINE_INFO_VLQ_SHIFT; + } while (value > 0); + + buffer_p[length - 1] &= ECMA_LINE_INFO_VLQ_MASK; + return length; +} /* parser_line_info_encode_vlq */ + +/** + * Encodes an uint32_t number into a buffer. Numbers expected to be smaller values. + * + * @return the number of bytes written to the buffer + */ +static uint32_t +parser_line_info_encode_small (uint8_t *buffer_p, /**< target buffer */ + uint32_t value) /**< encoded value */ +{ + if (JERRY_LIKELY (value < ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN)) + { + buffer_p[0] = (uint8_t) value; + return 1; + } + + if (JERRY_LIKELY (value < ECMA_LINE_INFO_ENCODE_VLQ_MIN)) + { + buffer_p[0] = ECMA_LINE_INFO_ENCODE_TWO_BYTE; + buffer_p[1] = (uint8_t) (value - ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN); + return 2; + } + + *buffer_p++ = ECMA_LINE_INFO_ENCODE_VLQ; + return parser_line_info_encode_vlq (buffer_p, value - ECMA_LINE_INFO_ENCODE_VLQ_MIN) + 1; +} /* parser_line_info_encode_small */ + +/** + * Encodes the difference between two values. + * + * @return encoded difference + */ +static inline uint32_t +parser_line_info_difference_get (uint32_t current_value, /**< current value */ + uint32_t prev_value) /**< previous value */ +{ + uint32_t result = current_value - prev_value - 1; + + if (result <= (UINT32_MAX >> 1)) + { + return (result << 1) | ECMA_LINE_INFO_INCREASE; + } + + return ((UINT32_MAX - result) << 1) | ECMA_LINE_INFO_DECREASE; +} /* parser_line_info_difference_get */ + +/** + * Appends a value at the end of the line info stream. + */ +static void +parser_line_info_append_number (parser_context_t *context_p, /**< context */ + uint32_t value) /**< value to be encoded */ +{ + parser_line_info_data_t *line_info_p = context_p->line_info_p; + uint8_t buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE]; + + JERRY_ASSERT (line_info_p != NULL); + + uint32_t length = parser_line_info_encode_vlq (buffer, value); + uint8_t offset = line_info_p->last_page_p->bytes[0]; + + if (offset + length <= PARSER_STACK_PAGE_SIZE) + { + memcpy (line_info_p->last_page_p->bytes + offset, buffer, length); + + line_info_p->last_page_p->bytes[0] = (uint8_t) (length + offset); + return; + } + + parser_mem_page_t *new_page_p; + new_page_p = (parser_mem_page_t *) parser_malloc (context_p, PARSER_LINE_INFO_PAGE_SIZE); + + new_page_p->next_p = NULL; + + line_info_p->last_page_p->next_p = new_page_p; + line_info_p->last_page_p = new_page_p; + + new_page_p->bytes[0] = (uint8_t) (length + 1); + memcpy (new_page_p->bytes + 1, buffer, length); +} /* parser_line_info_append_number */ + +/** + * Updates the current line information data. + */ +void +parser_line_info_append (parser_context_t *context_p, /**< context */ + parser_line_counter_t line, /**< line */ + parser_line_counter_t column) /**< column */ +{ + parser_line_info_data_t *line_info_p = context_p->line_info_p; + uint32_t value; + + if (line_info_p != NULL) + { + if (line_info_p->byte_code_position == context_p->byte_code_size + || (line_info_p->line == line && line_info_p->column == column)) + { + return; + } + + /* Sets ECMA_LINE_INFO_HAS_LINE bit. */ + value = (uint32_t) (line != line_info_p->line); + } + else + { + line_info_p = (parser_line_info_data_t *) parser_malloc (context_p, PARSER_LINE_INFO_FIRST_PAGE_SIZE); + context_p->line_info_p = line_info_p; + + parser_mem_page_t *page_p = PARSER_LINE_INFO_GET_FIRST_PAGE (line_info_p); + page_p->next_p = NULL; + page_p->bytes[0] = 1; + + line_info_p->last_page_p = page_p; + line_info_p->byte_code_position = 0; + line_info_p->line = 1; + line_info_p->column = 1; + + /* Sets ECMA_LINE_INFO_HAS_LINE bit. */ + value = (uint32_t) (line != 1); + } + + value |= ((context_p->byte_code_size - line_info_p->byte_code_position) << 1); + + parser_line_info_append_number (context_p, value); + line_info_p->byte_code_position = context_p->byte_code_size; + + if (value & ECMA_LINE_INFO_HAS_LINE) + { + value = parser_line_info_difference_get (line, line_info_p->line); + parser_line_info_append_number (context_p, value); + line_info_p->line = line; + } + + value = parser_line_info_difference_get (column, line_info_p->column); + parser_line_info_append_number (context_p, value); + line_info_p->column = column; +} /* parser_line_info_append */ + +/** + * Line info iterator structure + */ +typedef struct +{ + parser_mem_page_t *current_page_p; /**< current page */ + uint32_t offset; /**< current offset */ +} parser_line_info_iterator_t; + +/** + * Decodes the next value from the iterator stream + */ +static uint32_t +parser_line_info_iterator_get (parser_line_info_iterator_t *iterator_p) /**< iterator */ +{ + uint8_t *source_p = iterator_p->current_page_p->bytes + iterator_p->offset; + uint32_t result = ecma_line_info_decode_vlq (&source_p); + + iterator_p->offset = (uint32_t) (source_p - iterator_p->current_page_p->bytes); + + JERRY_ASSERT (iterator_p->offset <= iterator_p->current_page_p->bytes[0]); + + if (iterator_p->offset < iterator_p->current_page_p->bytes[0]) + { + return result; + } + + iterator_p->current_page_p = iterator_p->current_page_p->next_p; + iterator_p->offset = 1; + return result; +} /* parser_line_info_iterator_get */ + +/** + * Generate line info data + * + * @return generated line info data + */ +uint8_t * +parser_line_info_generate (parser_context_t *context_p) /**< context */ +{ + parser_line_info_iterator_t iterator; + uint8_t *line_info_p = NULL; + uint8_t *dst_p = NULL; + uint32_t total_length = 0; + uint32_t total_length_size = 0; + + while (true) + { + /* The following code runs twice: first the size of the data, + * is computed and the data is generated during the second run. + * Note: line_info_p is NULL during the first run. */ + parser_mem_page_t *iterator_byte_code_page_p = context_p->byte_code.first_p; + uint32_t iterator_byte_code_page_offset = 0; + uint32_t iterator_byte_code_base = 0; + uint32_t iterator_last_byte_code_offset = UINT32_MAX; + uint32_t iterator_prev_line = 0; + uint32_t iterator_prev_column = 0; + uint32_t iterator_line = 1; + uint32_t iterator_column = 1; + uint8_t block_buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE]; + uint8_t line_column_buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE * 2]; + uint8_t *block_size_p = NULL; + uint32_t block_byte_code_offset = 0; + uint32_t block_prev_line = 1; + uint32_t stream_byte_code_offset = 0; + uint32_t stream_current_line = 1; + uint32_t stream_current_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t stream_prev_line = 1; + uint32_t stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + uint32_t stream_size = 0; + uint32_t stream_value_count = 0; + uint32_t value; + + iterator.current_page_p = PARSER_LINE_INFO_GET_FIRST_PAGE (context_p->line_info_p); + iterator.offset = 1; + + do + { + /* Decode line information generated during parsing. */ + value = parser_line_info_iterator_get (&iterator); + iterator_byte_code_page_offset += (value >> 1); + + if (value & 0x1) + { + value = parser_line_info_iterator_get (&iterator); + JERRY_ASSERT (value != ((0 << 1) | ECMA_LINE_INFO_DECREASE)); + iterator_line = ecma_line_info_difference_update (iterator_line, value); + } + + value = parser_line_info_iterator_get (&iterator); + iterator_column = ecma_line_info_difference_update (iterator_column, value); + + while (iterator_byte_code_page_offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + uint8_t relative_offset = iterator_byte_code_page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1]; + iterator_byte_code_base += relative_offset & CBC_LOWER_SEVEN_BIT_MASK; + iterator_byte_code_page_offset -= PARSER_CBC_STREAM_PAGE_SIZE; + iterator_byte_code_page_p = iterator_byte_code_page_p->next_p; + } + + uint32_t iterator_byte_code_offset = iterator_byte_code_base; + + if (iterator_byte_code_page_offset > 0) + { + uint8_t relative_offset = iterator_byte_code_page_p->bytes[iterator_byte_code_page_offset - 1]; + iterator_byte_code_offset += relative_offset & CBC_LOWER_SEVEN_BIT_MASK; + } + + /* Skip those line/column pairs which byte code was discarded during post processing + * or does not change line/column (this is possible when multiple skips occures). */ + if (iterator_byte_code_offset == iterator_last_byte_code_offset + || (iterator_line == iterator_prev_line && iterator_column == iterator_prev_column)) + { + continue; + } + + iterator_prev_line = iterator_line; + iterator_prev_column = iterator_column; + iterator_last_byte_code_offset = iterator_byte_code_offset; + + if (block_size_p != NULL) + { + /* Sets ECMA_LINE_INFO_HAS_LINE bit. */ + value = (((iterator_byte_code_offset - stream_byte_code_offset) << 1) + | (uint32_t) (stream_prev_line != stream_current_line)); + + uint32_t line_column_size = 0; + uint32_t offset_size = parser_line_info_encode_small (block_buffer, value); + stream_byte_code_offset = iterator_byte_code_offset; + + if (value & ECMA_LINE_INFO_HAS_LINE) + { + value = parser_line_info_difference_get (stream_current_line, stream_prev_line); + line_column_size = parser_line_info_encode_small (line_column_buffer, value); + stream_prev_line = stream_current_line; + stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + value = parser_line_info_difference_get (stream_current_column, stream_prev_column); + line_column_size += parser_line_info_encode_small (line_column_buffer + line_column_size, value); + + stream_prev_column = stream_current_column; + stream_current_line = iterator_line; + stream_current_column = iterator_column; + + stream_value_count++; + + if (stream_value_count < ECMA_LINE_INFO_STREAM_VALUE_COUNT_MAX + && (stream_size + offset_size + line_column_size <= PARSER_LINE_INFO_STREAM_SIZE_LIMIT)) + { + stream_size += offset_size + line_column_size; + + if (line_info_p != NULL) + { + memcpy (dst_p, block_buffer, offset_size); + dst_p += offset_size; + memcpy (dst_p, line_column_buffer, line_column_size); + dst_p += line_column_size; + } + continue; + } + + /* Finalize the current chunk. The size of EndOffset is always 1. */ + stream_size += 1 + line_column_size; + + JERRY_ASSERT (stream_size > ECMA_LINE_INFO_STREAM_SIZE_MIN + && (stream_size - ECMA_LINE_INFO_STREAM_SIZE_MIN) <= UINT8_MAX); + + if (line_info_p != NULL) + { + *block_size_p = (uint8_t) (stream_size - ECMA_LINE_INFO_STREAM_SIZE_MIN); + /* Set EndOffset to 0 and copy the has_line bit. */ + *dst_p++ = (uint8_t) (block_buffer[0] & ECMA_LINE_INFO_HAS_LINE); + memcpy (dst_p, line_column_buffer, line_column_size); + dst_p += line_column_size; + } + else + { + total_length += stream_size; + dst_p = block_buffer; + } + + uint32_t byte_code_diff = iterator_last_byte_code_offset - block_byte_code_offset; + dst_p += parser_line_info_encode_vlq (dst_p, byte_code_diff); + block_byte_code_offset = iterator_last_byte_code_offset; + + if (line_info_p == NULL) + { + total_length += (uint32_t) (dst_p - block_buffer); + } + } + + /* Start a new chunk. */ + if (line_info_p == NULL) + { + dst_p = block_buffer; + } + + value = parser_line_info_difference_get (iterator_line, block_prev_line); + + dst_p += parser_line_info_encode_vlq (dst_p, value); + block_size_p = dst_p; + dst_p++; + + if (line_info_p == NULL) + { + total_length += (uint32_t) (dst_p - block_buffer); + } + + block_prev_line = iterator_line; + stream_current_line = iterator_line; + stream_current_column = iterator_column; + stream_prev_line = iterator_line; + stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + stream_size = 0; + stream_value_count = 0; + } while (iterator.current_page_p != NULL); + + value = (stream_prev_line != stream_current_line); + + /* Finalize the last stream */ + if (line_info_p == NULL) + { + dst_p = line_column_buffer; + total_length += stream_size + 1; + } + else + { + *block_size_p = 0; + /* Small encoded value of has_line bit. */ + *dst_p++ = (uint8_t) value; + } + + if (value) + { + value = parser_line_info_difference_get (stream_current_line, stream_prev_line); + dst_p += parser_line_info_encode_small (dst_p, value); + stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT; + } + + value = parser_line_info_difference_get (stream_current_column, stream_prev_column); + dst_p += parser_line_info_encode_small (dst_p, value); + + if (line_info_p == NULL) + { + total_length += (uint32_t) (dst_p - line_column_buffer); + } + + if (line_info_p != NULL) + { + break; + } + + total_length_size = parser_line_info_encode_vlq (block_buffer, total_length); + + /* TODO: Support allocation fail. */ + line_info_p = (uint8_t *) jmem_heap_alloc_block (total_length + total_length_size); + dst_p = line_info_p + parser_line_info_encode_vlq (line_info_p, total_length); + } + + JERRY_ASSERT (line_info_p + total_length_size + total_length == dst_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + ecma_line_info_dump (line_info_p); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + return line_info_p; +} /* parser_line_info_generate */ + +#endif /* JERRY_LINE_INFO */ + +#endif /* JERRY_PARSER */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-mem.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-mem.cpp new file mode 100644 index 00000000..4c8d2b62 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-mem.cpp @@ -0,0 +1,729 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_PARSER + +/** \addtogroup mem Memory allocation + * @{ + * + * \addtogroup mem_parser Parser memory manager + * @{ + */ + +/**********************************************************************/ +/* Memory allocation */ +/**********************************************************************/ + +/** + * Allocate memory. + * + * @return allocated memory. + */ +void * +parser_malloc (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + void *result; + + JERRY_ASSERT (size > 0); + result = jmem_heap_alloc_block_null_on_error (size); + + if (result == NULL) + { + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + return result; +} /* parser_malloc */ + +/** + * Free memory allocated by parser_malloc. + */ +void +parser_free (void *ptr, /**< pointer to free */ + size_t size) /**< size of the memory block */ +{ + jmem_heap_free_block (ptr, size); +} /* parser_free */ + +/** + * Allocate local memory for short term use. + * + * @return allocated memory. + */ +void * +parser_malloc_local (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory */ +{ + void *result; + + JERRY_ASSERT (size > 0); + result = jmem_heap_alloc_block (size); + if (result == 0) + { + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + return result; +} /* parser_malloc_local */ + +/** + * Free memory allocated by parser_malloc_local. + */ +void +parser_free_local (void *ptr, /**< pointer to free */ + size_t size) /**< size of the memory */ +{ + jmem_heap_free_block (ptr, size); +} /* parser_free_local */ + +/** + * Free the dynamically allocated buffer stored in the context + */ +void +parser_free_allocated_buffer (parser_context_t *context_p) /**< context */ +{ + if (context_p->u.allocated_buffer_p != NULL) + { + parser_free_local (context_p->u.allocated_buffer_p, context_p->allocated_buffer_size); + context_p->u.allocated_buffer_p = NULL; + } +} /* parser_free_allocated_buffer */ + +/**********************************************************************/ +/* Parser data management functions */ +/**********************************************************************/ + +/** + * Initialize parse data. + */ +static void +parser_data_init (parser_mem_data_t *data_p, /**< memory manager */ + uint32_t page_size) /**< size of each page */ +{ + data_p->first_p = NULL; + data_p->last_p = NULL; + data_p->last_position = page_size; +} /* parser_data_init */ + +/** + * Free parse data. + */ +static void +parser_data_free (parser_mem_data_t *data_p, /**< memory manager */ + uint32_t page_size) /**< size of each page */ +{ + parser_mem_page_t *page_p = data_p->first_p; + + while (page_p != NULL) + { + parser_mem_page_t *next_p = page_p->next_p; + + parser_free (page_p, page_size); + page_p = next_p; + } +} /* parser_data_free */ + +/**********************************************************************/ +/* Parser byte stream management functions */ +/**********************************************************************/ + +/** + * Initialize byte stream. + */ +void +parser_cbc_stream_init (parser_mem_data_t *data_p) /**< memory manager */ +{ + parser_data_init (data_p, PARSER_CBC_STREAM_PAGE_SIZE); +} /* parser_cbc_stream_init */ + +/** + * Free byte stream. + */ +void +parser_cbc_stream_free (parser_mem_data_t *data_p) /**< memory manager */ +{ + parser_data_free (data_p, sizeof (parser_mem_page_t *) + PARSER_CBC_STREAM_PAGE_SIZE); +} /* parser_cbc_stream_free */ + +/** + * Appends a byte at the end of the byte stream. + */ +void +parser_cbc_stream_alloc_page (parser_context_t *context_p, /**< context */ + parser_mem_data_t *data_p) /**< memory manager */ +{ + size_t size = sizeof (parser_mem_page_t *) + PARSER_CBC_STREAM_PAGE_SIZE; + parser_mem_page_t *page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + + page_p->next_p = NULL; + data_p->last_position = 0; + + if (data_p->last_p != NULL) + { + data_p->last_p->next_p = page_p; + } + else + { + data_p->first_p = page_p; + } + data_p->last_p = page_p; +} /* parser_cbc_stream_alloc_page */ + +/**********************************************************************/ +/* Parser list management functions */ +/**********************************************************************/ + +/** + * Initialize parser list. + */ +void +parser_list_init (parser_list_t *list_p, /**< parser list */ + uint32_t item_size, /**< size for each page */ + uint32_t item_count) /**< number of items on each page */ +{ + /* Align to pointer size. */ + item_size = (uint32_t) (((item_size) + sizeof (void *) - 1) & ~(sizeof (void *) - 1)); + parser_data_init (&list_p->data, item_size * item_count); + list_p->page_size = item_size * item_count; + list_p->item_size = item_size; + list_p->item_count = item_count; +} /* parser_list_init */ + +/** + * Free parser list. + */ +void +parser_list_free (parser_list_t *list_p) /**< parser list */ +{ + parser_data_free (&list_p->data, (uint32_t) (sizeof (parser_mem_page_t *) + list_p->page_size)); +} /* parser_list_free */ + +/** + * Reset parser list. + */ +void +parser_list_reset (parser_list_t *list_p) /**< parser list */ +{ + parser_data_init (&list_p->data, list_p->page_size); +} /* parser_list_reset */ + +/** + * Allocate space for the next item. + * + * @return pointer to the appended item. + */ +void * +parser_list_append (parser_context_t *context_p, /**< context */ + parser_list_t *list_p) /**< parser list */ +{ + parser_mem_page_t *page_p = list_p->data.last_p; + void *result; + + if (list_p->data.last_position + list_p->item_size > list_p->page_size) + { + size_t size = sizeof (parser_mem_page_t *) + list_p->page_size; + + page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + + page_p->next_p = NULL; + list_p->data.last_position = 0; + + if (list_p->data.last_p != NULL) + { + list_p->data.last_p->next_p = page_p; + } + else + { + list_p->data.first_p = page_p; + } + list_p->data.last_p = page_p; + } + + result = page_p->bytes + list_p->data.last_position; + list_p->data.last_position += list_p->item_size; + return result; +} /* parser_list_append */ + +/** + * Return the nth item of the list. + * + * @return pointer to the item. + */ +void * +parser_list_get (parser_list_t *list_p, /**< parser list */ + size_t index) /**< item index */ +{ + size_t item_count = list_p->item_count; + parser_mem_page_t *page_p = list_p->data.first_p; + + while (index >= item_count) + { + JERRY_ASSERT (page_p != NULL); + page_p = page_p->next_p; + index -= item_count; + } + + JERRY_ASSERT (page_p != NULL); + JERRY_ASSERT (page_p != list_p->data.last_p || (index * list_p->item_size < list_p->data.last_position)); + return page_p->bytes + (index * list_p->item_size); +} /* parser_list_get */ + +/** + * Initialize a parser list iterator. + */ +void +parser_list_iterator_init (parser_list_t *list_p, /**< parser list */ + parser_list_iterator_t *iterator_p) /**< iterator */ +{ + iterator_p->list_p = list_p; + iterator_p->current_p = list_p->data.first_p; + iterator_p->current_position = 0; +} /* parser_list_iterator_init */ + +/** + * Next iterator step. + * + * @return the address of the current item, or NULL at the end. + */ +void * +parser_list_iterator_next (parser_list_iterator_t *iterator_p) /**< iterator */ +{ + void *result; + + if (iterator_p->current_p == NULL) + { + return NULL; + } + + result = iterator_p->current_p->bytes + iterator_p->current_position; + iterator_p->current_position += iterator_p->list_p->item_size; + + if (iterator_p->current_p->next_p == NULL) + { + if (iterator_p->current_position >= iterator_p->list_p->data.last_position) + { + iterator_p->current_p = NULL; + iterator_p->current_position = 0; + } + } + else if (iterator_p->current_position >= iterator_p->list_p->page_size) + { + iterator_p->current_p = iterator_p->current_p->next_p; + iterator_p->current_position = 0; + } + return result; +} /* parser_list_iterator_next */ + +/**********************************************************************/ +/* Parser stack management functions */ +/**********************************************************************/ + +/* Stack is a reversed storage. */ + +/** + * Initialize parser stack. + */ +void +parser_stack_init (parser_context_t *context_p) /**< context */ +{ + parser_data_init (&context_p->stack, PARSER_STACK_PAGE_SIZE); + context_p->free_page_p = NULL; +} /* parser_stack_init */ + +/** + * Free parser stack. + */ +void +parser_stack_free (parser_context_t *context_p) /**< context */ +{ + parser_data_free (&context_p->stack, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + + if (context_p->free_page_p != NULL) + { + parser_free (context_p->free_page_p, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + } +} /* parser_stack_free */ + +/** + * Pushes an uint8_t value onto the stack. + */ +void +parser_stack_push_uint8 (parser_context_t *context_p, /**< context */ + uint8_t uint8_value) /**< value pushed onto the stack */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + /* This assert might trigger false positive valgrind errors, when + * parser_stack_push() pushes not fully initialized structures. + * More precisely when the last byte of the structure is uninitialized. */ + JERRY_ASSERT (page_p == NULL || context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + if (context_p->stack.last_position >= PARSER_STACK_PAGE_SIZE) + { + if (context_p->free_page_p != NULL) + { + page_p = context_p->free_page_p; + context_p->free_page_p = NULL; + } + else + { + size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE; + page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + } + + page_p->next_p = context_p->stack.first_p; + context_p->stack.last_position = 0; + context_p->stack.first_p = page_p; + } + + page_p->bytes[context_p->stack.last_position++] = uint8_value; + context_p->stack_top_uint8 = uint8_value; +} /* parser_stack_push_uint8 */ + +/** + * Pops the last uint8_t value from the stack. + */ +void +parser_stack_pop_uint8 (parser_context_t *context_p) /**< context */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + context_p->stack.last_position--; + + if (context_p->stack.last_position == 0) + { + context_p->stack.first_p = page_p->next_p; + context_p->stack.last_position = PARSER_STACK_PAGE_SIZE; + + if (context_p->free_page_p == NULL) + { + context_p->free_page_p = page_p; + } + else + { + parser_free (page_p, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + } + + page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL); + } + + context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 1]; +} /* parser_stack_pop_uint8 */ + +/** + * Change last byte of the stack. + */ +void +parser_stack_change_last_uint8 (parser_context_t *context_p, /**< context */ + uint8_t new_value) /**< new value */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + page_p->bytes[context_p->stack.last_position - 1] = new_value; + context_p->stack_top_uint8 = new_value; +} /* parser_stack_change_last_uint8 */ + +/** + * Get the uint8 value before the top of the stack. + * + * Pointer to the uint8 value + */ +uint8_t * +parser_stack_get_prev_uint8 (parser_context_t *context_p) /**< context */ +{ + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && (context_p->stack.last_position >= 2 || page_p->next_p != NULL)); + + if (context_p->stack.last_position >= 2) + { + return page_p->bytes + (context_p->stack.last_position - 2); + } + + return page_p->next_p->bytes + (PARSER_STACK_PAGE_SIZE - 1); +} /* parser_stack_get_prev_uint8 */ + +/** + * Pushes an uint16_t value onto the stack. + */ +void +parser_stack_push_uint16 (parser_context_t *context_p, /**< context */ + uint16_t uint16_value) /**< value pushed onto the stack */ +{ + if (context_p->stack.last_position + 2 <= PARSER_STACK_PAGE_SIZE) + { + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + page_p->bytes[context_p->stack.last_position++] = (uint8_t) (uint16_value >> 8); + page_p->bytes[context_p->stack.last_position++] = (uint8_t) uint16_value; + context_p->stack_top_uint8 = (uint8_t) uint16_value; + } + else + { + parser_stack_push_uint8 (context_p, (uint8_t) (uint16_value >> 8)); + parser_stack_push_uint8 (context_p, (uint8_t) uint16_value); + } +} /* parser_stack_push_uint16 */ + +/** + * Pops the last uint16_t value from the stack. + * + * @return the value popped from the stack. + */ +uint16_t +parser_stack_pop_uint16 (parser_context_t *context_p) /**< context */ +{ + uint32_t value = context_p->stack_top_uint8; + + if (context_p->stack.last_position >= 3) + { + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (page_p != NULL && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); + + value |= ((uint32_t) page_p->bytes[context_p->stack.last_position - 2]) << 8; + context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 3]; + context_p->stack.last_position -= 2; + } + else + { + parser_stack_pop_uint8 (context_p); + value |= ((uint32_t) context_p->stack_top_uint8) << 8; + parser_stack_pop_uint8 (context_p); + } + return (uint16_t) value; +} /* parser_stack_pop_uint16 */ + +/** + * Pushes a data onto the stack. + */ +void +parser_stack_push (parser_context_t *context_p, /**< context */ + const void *data_p, /**< data pushed onto the stack */ + uint32_t length) /**< length of the data */ +{ + uint32_t fragment_length = PARSER_STACK_PAGE_SIZE - context_p->stack.last_position; + const uint8_t *bytes_p = (const uint8_t *) data_p; + parser_mem_page_t *page_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + context_p->stack_top_uint8 = bytes_p[length - 1]; + + if (fragment_length > 0) + { + /* Fill the remaining bytes. */ + if (fragment_length > length) + { + fragment_length = length; + } + + memcpy (context_p->stack.first_p->bytes + context_p->stack.last_position, bytes_p, fragment_length); + + if (fragment_length == length) + { + context_p->stack.last_position += length; + return; + } + + bytes_p += fragment_length; + length -= fragment_length; + } + + if (context_p->free_page_p != NULL) + { + page_p = context_p->free_page_p; + context_p->free_page_p = NULL; + } + else + { + size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE; + + page_p = (parser_mem_page_t *) parser_malloc (context_p, size); + } + + page_p->next_p = context_p->stack.first_p; + + context_p->stack.first_p = page_p; + + memcpy (page_p->bytes, bytes_p, length); + context_p->stack.last_position = length; +} /* parser_stack_push */ + +/** + * Pop bytes from the top of the stack. + */ +void +parser_stack_pop (parser_context_t *context_p, /**< context */ + void *data_p, /**< destination buffer, can be NULL */ + uint32_t length) /**< length of the data */ +{ + uint8_t *bytes_p = (uint8_t *) data_p; + parser_mem_page_t *page_p = context_p->stack.first_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (context_p->stack.last_position > length) + { + context_p->stack.last_position -= length; + context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 1]; + + if (bytes_p != NULL) + { + memcpy (bytes_p, context_p->stack.first_p->bytes + context_p->stack.last_position, length); + } + return; + } + + JERRY_ASSERT (page_p->next_p != NULL); + + length -= context_p->stack.last_position; + + if (bytes_p != NULL) + { + memcpy (bytes_p + length, page_p->bytes, context_p->stack.last_position); + } + + context_p->stack.first_p = page_p->next_p; + context_p->stack.last_position = PARSER_STACK_PAGE_SIZE - length; + context_p->stack_top_uint8 = page_p->next_p->bytes[context_p->stack.last_position - 1]; + + if (bytes_p != NULL && length > 0) + { + memcpy (bytes_p, page_p->next_p->bytes + context_p->stack.last_position, length); + } + + JERRY_ASSERT (context_p->stack.last_position > 0); + + if (context_p->free_page_p == NULL) + { + context_p->free_page_p = page_p; + } + else + { + parser_free (page_p, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); + } +} /* parser_stack_pop */ + +/** + * Initialize stack iterator. + */ +void +parser_stack_iterator_init (parser_context_t *context_p, /**< context */ + parser_stack_iterator_t *iterator) /**< iterator */ +{ + iterator->current_p = context_p->stack.first_p; + iterator->current_position = context_p->stack.last_position; +} /* parser_stack_iterator_init */ + +/** + * Read the next byte from the stack. + * + * @return byte + */ +uint8_t +parser_stack_iterator_read_uint8 (parser_stack_iterator_t *iterator) /**< iterator */ +{ + JERRY_ASSERT (iterator->current_position > 0 && iterator->current_position <= PARSER_STACK_PAGE_SIZE); + return iterator->current_p->bytes[iterator->current_position - 1]; +} /* parser_stack_iterator_read_uint8 */ + +/** + * Skip the next n bytes of the stack. + */ +void +parser_stack_iterator_skip (parser_stack_iterator_t *iterator, /**< iterator */ + size_t length) /**< number of skipped bytes */ +{ + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (length < iterator->current_position) + { + iterator->current_position -= length; + } + else + { + iterator->current_position = PARSER_STACK_PAGE_SIZE - (length - iterator->current_position); + iterator->current_p = iterator->current_p->next_p; + } +} /* parser_stack_iterator_skip */ + +/** + * Read bytes from the stack. + */ +void +parser_stack_iterator_read (parser_stack_iterator_t *iterator, /**< iterator */ + void *data_p, /**< destination buffer */ + size_t length) /**< length of the data */ +{ + uint8_t *bytes_p = (uint8_t *) data_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (length <= iterator->current_position) + { + memcpy (bytes_p, iterator->current_p->bytes + iterator->current_position - length, length); + } + else + { + JERRY_ASSERT (iterator->current_p->next_p != NULL); + + length -= iterator->current_position; + memcpy (bytes_p + length, iterator->current_p->bytes, iterator->current_position); + memcpy (bytes_p, iterator->current_p->next_p->bytes + PARSER_STACK_PAGE_SIZE - length, length); + } +} /* parser_stack_iterator_read */ + +/** + * Write bytes onto the stack. + */ +void +parser_stack_iterator_write (parser_stack_iterator_t *iterator, /**< iterator */ + const void *data_p, /**< destination buffer */ + size_t length) /**< length of the data */ +{ + const uint8_t *bytes_p = (const uint8_t *) data_p; + + JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); + + if (length <= iterator->current_position) + { + memcpy (iterator->current_p->bytes + iterator->current_position - length, bytes_p, length); + } + else + { + JERRY_ASSERT (iterator->current_p->next_p != NULL); + + length -= iterator->current_position; + memcpy (iterator->current_p->bytes, bytes_p + length, iterator->current_position); + memcpy (iterator->current_p->next_p->bytes + PARSER_STACK_PAGE_SIZE - length, bytes_p, length); + } +} /* parser_stack_iterator_write */ + +/** + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-module.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-module.cpp new file mode 100644 index 00000000..465f8122 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-module.cpp @@ -0,0 +1,529 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_MODULE_SYSTEM +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-module.h" + +#include "jcontext.h" + +/** + * Description of "*default*" literal string. + */ +const lexer_lit_location_t lexer_default_literal = { (const uint8_t *) "*default*", + 9, + LEXER_IDENT_LITERAL, + LEXER_LIT_LOCATION_IS_ASCII }; + +/** + * Check for duplicated imported binding names. + * + * @return true - if the given name is a duplicate + * false - otherwise + */ +bool +parser_module_check_duplicate_import (parser_context_t *context_p, /**< parser context */ + ecma_string_t *local_name_p) /**< newly imported name */ +{ + ecma_module_names_t *module_names_p = context_p->module_names_p; + + while (module_names_p != NULL) + { + if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p)) + { + return true; + } + + module_names_p = module_names_p->next_p; + } + + ecma_module_node_t *module_node_p = JERRY_CONTEXT (module_current_p)->imports_p; + + while (module_node_p != NULL) + { + module_names_p = module_node_p->module_names_p; + + while (module_names_p != NULL) + { + if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p)) + { + return true; + } + + module_names_p = module_names_p->next_p; + } + + module_node_p = module_node_p->next_p; + } + + return false; +} /* parser_module_check_duplicate_import */ + +/** + * Append an identifier to the exported bindings. + */ +void +parser_module_append_export_name (parser_context_t *context_p) /**< parser context */ +{ + if (!(context_p->status_flags & PARSER_MODULE_STORE_IDENT)) + { + return; + } + + context_p->module_identifier_lit_p = context_p->lit_object.literal_p; + ecma_string_t *name_p = parser_new_ecma_string_from_literal (context_p->lit_object.literal_p); + + if (parser_module_check_duplicate_export (context_p, name_p)) + { + ecma_deref_ecma_string (name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + parser_module_add_names_to_node (context_p, name_p, name_p); + ecma_deref_ecma_string (name_p); +} /* parser_module_append_export_name */ + +/** + * Check for duplicated exported bindings. + * @return - true - if the exported name is a duplicate + * false - otherwise + */ +bool +parser_module_check_duplicate_export (parser_context_t *context_p, /**< parser context */ + ecma_string_t *export_name_p) /**< exported identifier */ +{ + /* We have to check in the currently constructed node, as well as all of the already added nodes. */ + ecma_module_names_t *current_names_p = context_p->module_names_p; + + while (current_names_p != NULL) + { + if (ecma_compare_ecma_strings (current_names_p->imex_name_p, export_name_p)) + { + return true; + } + current_names_p = current_names_p->next_p; + } + + ecma_module_names_t *name_p = JERRY_CONTEXT (module_current_p)->local_exports_p; + + while (name_p != NULL) + { + if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p)) + { + return true; + } + + name_p = name_p->next_p; + } + + ecma_module_node_t *export_node_p = JERRY_CONTEXT (module_current_p)->indirect_exports_p; + + while (export_node_p != NULL) + { + name_p = export_node_p->module_names_p; + + while (name_p != NULL) + { + if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p)) + { + return true; + } + + name_p = name_p->next_p; + } + + export_node_p = export_node_p->next_p; + } + + /* Star exports don't have any names associated with them, so no need to check those. */ + return false; +} /* parser_module_check_duplicate_export */ + +/** + * Add module names to current module node. + */ +void +parser_module_add_names_to_node (parser_context_t *context_p, /**< parser context */ + ecma_string_t *imex_name_p, /**< import/export name */ + ecma_string_t *local_name_p) /**< local name */ +{ + ecma_module_names_t *new_name_p = (ecma_module_names_t *) parser_malloc (context_p, sizeof (ecma_module_names_t)); + + new_name_p->next_p = context_p->module_names_p; + context_p->module_names_p = new_name_p; + + JERRY_ASSERT (imex_name_p != NULL); + ecma_ref_ecma_string (imex_name_p); + new_name_p->imex_name_p = imex_name_p; + + JERRY_ASSERT (local_name_p != NULL); + ecma_ref_ecma_string (local_name_p); + new_name_p->local_name_p = local_name_p; +} /* parser_module_add_names_to_node */ + +/** + * Parse an ExportClause. + */ +void +parser_module_parse_export_clause (parser_context_t *context_p) /**< parser context */ +{ + bool has_module_specifier = false; + + if (context_p->source_p == context_p->next_scanner_info_p->source_p) + { + has_module_specifier = true; + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_EXPORT_MODULE_SPECIFIER); + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + lexer_next_token (context_p); + + while (true) + { + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + lexer_next_token (context_p); + break; + } + + /* 15.2.3.1 The referenced binding cannot be a reserved word. */ + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL + || context_p->token.keyword_type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + ecma_string_t *export_name_p = NULL; + ecma_string_t *local_name_p = NULL; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + if (!has_module_specifier && !scanner_literal_exists (context_p, context_p->lit_object.index)) + { + parser_raise_error (context_p, PARSER_ERR_EXPORT_NOT_DEFINED); + } + + uint16_t local_name_index = context_p->lit_object.index; + uint16_t export_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; + + lexer_next_token (context_p); + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + export_name_index = context_p->lit_object.index; + + lexer_next_token (context_p); + } + + local_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (local_name_index)); + + if (export_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + export_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (export_name_index)); + } + else + { + export_name_p = local_name_p; + ecma_ref_ecma_string (local_name_p); + } + + if (parser_module_check_duplicate_export (context_p, export_name_p)) + { + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (export_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + parser_module_add_names_to_node (context_p, export_name_p, local_name_p); + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (export_name_p); + + if (context_p->token.type != LEXER_COMMA && context_p->token.type != LEXER_RIGHT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED); + } + else if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + + if (lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + } +} /* parser_module_parse_export_clause */ + +/** + * Parse an ImportClause + */ +void +parser_module_parse_import_clause (parser_context_t *context_p) /**< parser context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE); + lexer_next_token (context_p); + + while (true) + { + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + lexer_next_token (context_p); + break; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + ecma_string_t *import_name_p = NULL; + ecma_string_t *local_name_p = NULL; + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + uint16_t import_name_index = context_p->lit_object.index; + uint16_t local_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; + + lexer_next_token (context_p); + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + local_name_index = context_p->lit_object.index; + + lexer_next_token (context_p); + } + + import_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (import_name_index)); + + if (local_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + local_name_p = parser_new_ecma_string_from_literal (PARSER_GET_LITERAL (local_name_index)); + } + else + { + local_name_p = import_name_p; + ecma_ref_ecma_string (local_name_p); + } + + if (parser_module_check_duplicate_import (context_p, local_name_p)) + { + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING); + } + + parser_module_add_names_to_node (context_p, import_name_p, local_name_p); + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + + if (context_p->token.type != LEXER_COMMA && (context_p->token.type != LEXER_RIGHT_BRACE)) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED); + } + else if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + + if (lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED); + } + } +} /* parser_module_parse_import_clause */ + +/** + * Raises parser error if the import or export statement is not in the global scope. + */ +void +parser_module_check_request_place (parser_context_t *context_p) /**< parser context */ +{ + if (context_p->last_context_p != NULL || context_p->stack_top_uint8 != 0 + || (context_p->status_flags & PARSER_IS_FUNCTION) || (context_p->global_status_flags & ECMA_PARSE_EVAL) + || (context_p->global_status_flags & ECMA_PARSE_MODULE) == 0) + { + parser_raise_error (context_p, PARSER_ERR_MODULE_UNEXPECTED); + } +} /* parser_module_check_request_place */ + +/** + * Append names to the names list. + */ +void +parser_module_append_names (parser_context_t *context_p, /**< parser context */ + ecma_module_names_t **module_names_p) /**< target names */ +{ + ecma_module_names_t *last_name_p = context_p->module_names_p; + + if (last_name_p == NULL) + { + return; + } + + if (*module_names_p != NULL) + { + while (last_name_p->next_p != NULL) + { + last_name_p = last_name_p->next_p; + } + + last_name_p->next_p = *module_names_p; + } + + *module_names_p = context_p->module_names_p; + context_p->module_names_p = NULL; +} /* parser_module_append_names */ + +/** + * Handle module specifier at the end of the import / export statement. + */ +void +parser_module_handle_module_specifier (parser_context_t *context_p, /**< parser context */ + ecma_module_node_t **node_list_p) /**< target node list */ +{ + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_STRING_LITERAL + || context_p->token.lit_location.length == 0) + { + parser_raise_error (context_p, PARSER_ERR_STRING_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + + lexer_literal_t *path_p = context_p->lit_object.literal_p; + + lexer_next_token (context_p); + + /* The lexer_next_token may throw an error, so the path is constructed after its call. */ + ecma_string_t *path_string_p = parser_new_ecma_string_from_literal (path_p); + + ecma_module_node_t *node_p = JERRY_CONTEXT (module_current_p)->imports_p; + ecma_module_node_t *last_node_p = NULL; + + /* Check if we have an import node with the same module request. */ + + while (node_p != NULL) + { + if (ecma_compare_ecma_strings (ecma_get_string_from_value (node_p->u.path_or_module), path_string_p)) + { + ecma_deref_ecma_string (path_string_p); + break; + } + + last_node_p = node_p; + node_p = node_p->next_p; + } + + if (node_p == NULL) + { + node_p = (ecma_module_node_t *) jmem_heap_alloc_block_null_on_error (sizeof (ecma_module_node_t)); + + if (node_p == NULL) + { + ecma_deref_ecma_string (path_string_p); + parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); + } + + if (last_node_p == NULL) + { + JERRY_CONTEXT (module_current_p)->imports_p = node_p; + } + else + { + last_node_p->next_p = node_p; + } + + node_p->next_p = NULL; + node_p->module_names_p = NULL; + node_p->u.path_or_module = ecma_make_string_value (path_string_p); + } + + /* Append to imports. */ + if (node_list_p == NULL) + { + parser_module_append_names (context_p, &node_p->module_names_p); + return; + } + + ecma_value_t *module_object_p = &node_p->u.path_or_module; + + node_p = *node_list_p; + last_node_p = NULL; + + while (node_p != NULL) + { + if (node_p->u.module_object_p == module_object_p) + { + parser_module_append_names (context_p, &node_p->module_names_p); + return; + } + + last_node_p = node_p; + node_p = node_p->next_p; + } + + node_p = (ecma_module_node_t *) parser_malloc (context_p, sizeof (ecma_module_node_t)); + + if (last_node_p == NULL) + { + *node_list_p = node_p; + } + else + { + last_node_p->next_p = node_p; + } + + node_p->next_p = NULL; + node_p->module_names_p = context_p->module_names_p; + node_p->u.module_object_p = module_object_p; + + context_p->module_names_p = NULL; +} /* parser_module_handle_module_specifier */ + +#endif /* JERRY_MODULE_SYSTEM */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-statm.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-statm.cpp new file mode 100644 index 00000000..51b51c11 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-statm.cpp @@ -0,0 +1,3315 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" + +#if JERRY_PARSER +#include "ecma-helpers.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_stmt Statement parser + * @{ + */ + +/** + * Parser statement types. + * + * When a new statement is added, the following + * arrays must be updated as well: + * - statement_lengths[] + * - parser_statement_flags[] + */ +typedef enum +{ + PARSER_STATEMENT_START, + PARSER_STATEMENT_BLOCK, + PARSER_STATEMENT_BLOCK_SCOPE, + PARSER_STATEMENT_PRIVATE_SCOPE, + PARSER_STATEMENT_BLOCK_CONTEXT, + PARSER_STATEMENT_PRIVATE_CONTEXT, + PARSER_STATEMENT_LABEL, + PARSER_STATEMENT_IF, + PARSER_STATEMENT_ELSE, + PARSER_STATEMENT_SWITCH, + PARSER_STATEMENT_SWITCH_NO_DEFAULT, + PARSER_STATEMENT_DO_WHILE, + PARSER_STATEMENT_WHILE, + PARSER_STATEMENT_FOR, + PARSER_STATEMENT_FOR_IN, + PARSER_STATEMENT_FOR_OF, + PARSER_STATEMENT_FOR_AWAIT_OF, + PARSER_STATEMENT_WITH, + PARSER_STATEMENT_TRY, +} parser_statement_type_t; + +/** + * Parser statement type flags. + */ +typedef enum +{ + PARSER_STATM_NO_OPTS = 0, /**< no options */ + PARSER_STATM_SINGLE_STATM = (1 << 0), /**< statment can form single statement context */ + PARSER_STATM_HAS_BLOCK = (1 << 1), /**< statement always has a code block */ + PARSER_STATM_BREAK_TARGET = (1 << 2), /**< break target statement */ + PARSER_STATM_CONTINUE_TARGET = (1 << 3), /**< continue target statement */ + PARSER_STATM_CONTEXT_BREAK = (1 << 4), /**< uses another instruction form when crosses their borders */ +} parser_statement_flags_t; + +/** + * Parser statement attributes. + * Note: the order of the attributes must be keep in sync with parser_statement_type_t + */ +static const uint8_t parser_statement_flags[] = { + /* PARSER_STATEMENT_START */ + PARSER_STATM_HAS_BLOCK, + /* PARSER_STATEMENT_BLOCK, */ + PARSER_STATM_HAS_BLOCK, + /* PARSER_STATEMENT_BLOCK_SCOPE, */ + PARSER_STATM_HAS_BLOCK, + /* PARSER_STATEMENT_PRIVATE_SCOPE, */ + PARSER_STATM_NO_OPTS, + /* PARSER_STATEMENT_BLOCK_CONTEXT, */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_PRIVATE_CONTEXT, */ + PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_LABEL */ + PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_IF */ + PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_ELSE */ + PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_SWITCH */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_BREAK_TARGET, + /* PARSER_STATEMENT_SWITCH_NO_DEFAULT */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_BREAK_TARGET, + /* PARSER_STATEMENT_DO_WHILE */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_WHILE */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_FOR */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_FOR_IN */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_FOR_OF */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_FOR_AWAIT_OF */ + PARSER_STATM_BREAK_TARGET | PARSER_STATM_CONTINUE_TARGET | PARSER_STATM_SINGLE_STATM | PARSER_STATM_CONTEXT_BREAK, + /* PARSER_STATEMENT_WITH */ + PARSER_STATM_CONTEXT_BREAK | PARSER_STATM_SINGLE_STATM, + /* PARSER_STATEMENT_TRY */ + PARSER_STATM_HAS_BLOCK | PARSER_STATM_CONTEXT_BREAK +}; + +/** + * Block statement. + */ +typedef struct +{ + uint16_t scope_stack_top; /**< preserved top of scope stack */ + uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */ +} parser_block_statement_t; + +/** + * Context of block statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ +} parser_block_context_t; + +/** + * Loop statement. + */ +typedef struct +{ + parser_branch_node_t *branch_list_p; /**< list of breaks and continues targeting this statement */ +} parser_loop_statement_t; + +/** + * Label statement. + */ +typedef struct +{ + lexer_lit_location_t label_ident; /**< name of the label */ + parser_branch_node_t *break_list_p; /**< list of breaks targeting this label */ +} parser_label_statement_t; + +/** + * If/else statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ +} parser_if_else_statement_t; + +/** + * Switch statement. + */ +typedef struct +{ + parser_branch_t default_branch; /**< branch to the default case */ + parser_branch_node_t *branch_list_p; /**< branches of case statements */ +} parser_switch_statement_t; + +/** + * Do-while statement. + */ +typedef struct +{ + uint32_t start_offset; /**< start byte code offset */ +} parser_do_while_statement_t; + +/** + * While statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ + scanner_location_t condition_location; /**< condition part */ + uint32_t start_offset; /**< start byte code offset */ +} parser_while_statement_t; + +/** + * For statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ + scanner_location_t condition_location; /**< condition part */ + scanner_location_t expression_location; /**< expression part */ + uint32_t start_offset; /**< start byte code offset */ +} parser_for_statement_t; + +/** + * For-in statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ + uint32_t start_offset; /**< start byte code offset */ +} parser_for_in_of_statement_t; + +/** + * With statement. + */ +typedef struct +{ + parser_branch_t branch; /**< branch to the end */ +} parser_with_statement_t; + +/** + * Lexer token types. + */ +typedef enum +{ + parser_try_block, /**< try block */ + parser_catch_block, /**< catch block */ + parser_finally_block, /**< finally block */ +} parser_try_block_type_t; + +/** + * Try statement. + */ +typedef struct +{ + parser_try_block_type_t type; /**< current block type */ + uint16_t scope_stack_top; /**< current top of scope stack */ + uint16_t scope_stack_reg_top; /**< current top register of scope stack */ + parser_branch_t branch; /**< branch to the end of the current block */ +} parser_try_statement_t; + +/** + * Returns the data consumed by a statement. It can be used + * to skip undesired frames on the stack during frame search. + * + * @return size consumed by a statement. + */ +static inline size_t +parser_statement_length (uint8_t type) /**< type of statement */ +{ + static const uint8_t statement_lengths[] = { + /* PARSER_STATEMENT_BLOCK */ + 1, + /* PARSER_STATEMENT_BLOCK_SCOPE */ + (uint8_t) (sizeof (parser_block_statement_t) + 1), + /* PARSER_STATEMENT_PRIVATE_SCOPE */ + (uint8_t) (sizeof (parser_block_statement_t) + 1), + /* PARSER_STATEMENT_BLOCK_CONTEXT */ + (uint8_t) (sizeof (parser_block_statement_t) + sizeof (parser_block_context_t) + 1), + /* PARSER_STATEMENT_PRIVATE_CONTEXT */ + (uint8_t) (sizeof (parser_block_statement_t) + sizeof (parser_block_context_t) + 1), + /* PARSER_STATEMENT_LABEL */ + (uint8_t) (sizeof (parser_label_statement_t) + 1), + /* PARSER_STATEMENT_IF */ + (uint8_t) (sizeof (parser_if_else_statement_t) + 1), + /* PARSER_STATEMENT_ELSE */ + (uint8_t) (sizeof (parser_if_else_statement_t) + 1), + /* PARSER_STATEMENT_SWITCH */ + (uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_SWITCH_NO_DEFAULT */ + (uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_DO_WHILE */ + (uint8_t) (sizeof (parser_do_while_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_WHILE */ + (uint8_t) (sizeof (parser_while_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR */ + (uint8_t) (sizeof (parser_for_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR_IN */ + (uint8_t) (sizeof (parser_for_in_of_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR_OF */ + (uint8_t) (sizeof (parser_for_in_of_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_FOR_AWAIT_OF */ + (uint8_t) (sizeof (parser_for_in_of_statement_t) + sizeof (parser_loop_statement_t) + 1), + /* PARSER_STATEMENT_WITH */ + (uint8_t) (sizeof (parser_with_statement_t) + 1 + 1), + /* PARSER_STATEMENT_TRY */ + (uint8_t) (sizeof (parser_try_statement_t) + 1), + }; + + JERRY_ASSERT (type >= PARSER_STATEMENT_BLOCK && type <= PARSER_STATEMENT_TRY); + + return statement_lengths[type - PARSER_STATEMENT_BLOCK]; +} /* parser_statement_length */ +/** + * Parse expression enclosed in parens. + */ +static inline void +parser_parse_enclosed_expr (parser_context_t *context_p) /**< context */ +{ + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + lexer_next_token (context_p); +} /* parser_parse_enclosed_expr */ + +/** + * Create a block context. + * + * @return true - when a context is created, false - otherwise + */ +static bool +parser_push_block_context (parser_context_t *context_p, /**< context */ + bool is_private) /**< is private (bound to a statement) context */ +{ + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + + parser_block_statement_t block_statement; + block_statement.scope_stack_top = context_p->scope_stack_top; + block_statement.scope_stack_reg_top = context_p->scope_stack_reg_top; + + bool is_context_needed = false; + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_block_context_t block_context; + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc_forward_branch (context_p, CBC_BLOCK_CREATE_CONTEXT, &block_context.branch); + parser_stack_push (context_p, &block_context, sizeof (parser_block_context_t)); + is_context_needed = true; + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + parser_stack_push (context_p, &block_statement, sizeof (parser_block_statement_t)); + + uint8_t statement_type; + + if (is_private) + { + statement_type = (is_context_needed ? PARSER_STATEMENT_PRIVATE_CONTEXT : PARSER_STATEMENT_PRIVATE_SCOPE); + } + else + { + statement_type = (is_context_needed ? PARSER_STATEMENT_BLOCK_CONTEXT : PARSER_STATEMENT_BLOCK_SCOPE); + } + + parser_stack_push_uint8 (context_p, statement_type); + + return is_context_needed; +} /* parser_push_block_context */ + +/** + * Pop block context. + */ +static void +parser_pop_block_context (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_CONTEXT + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT); + + uint8_t type = context_p->stack_top_uint8; + + parser_block_statement_t block_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &block_statement, sizeof (parser_block_statement_t)); + + context_p->scope_stack_top = block_statement.scope_stack_top; + context_p->scope_stack_reg_top = block_statement.scope_stack_reg_top; + + if (type == PARSER_STATEMENT_BLOCK_CONTEXT || type == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_block_context_t block_context; + parser_stack_pop (context_p, &block_context, sizeof (parser_block_context_t)); + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_set_branch_to_current_position (context_p, &block_context.branch); + } + + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_pop_block_context */ + +/** + * Validate lexical context for a declaration. + */ +static void +parser_validate_lexical_context (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_LET || context_p->token.type == LEXER_KEYW_CONST + || context_p->token.type == LEXER_KEYW_CLASS); + + if (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } +} /* parser_validate_lexical_context */ + +/** + * Parse var statement. + */ +static void +parser_parse_var_statement (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_VAR || context_p->token.type == LEXER_KEYW_LET + || context_p->token.type == LEXER_KEYW_CONST); + + uint8_t declaration_type = context_p->token.type; + + if (declaration_type != LEXER_KEYW_VAR) + { + parser_validate_lexical_context (context_p); + } + + while (true) + { + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)) + { + parser_pattern_flags_t flags = PARSER_PATTERN_BINDING; + + if (declaration_type == LEXER_KEYW_LET) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_LET); + } + else if (declaration_type == LEXER_KEYW_CONST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_CONST); + } + + parser_parse_initializer_by_next_char (context_p, flags); + } + else + { + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); +#if JERRY_LINE_INFO + parser_line_counter_t ident_column_counter = context_p->token.column; +#endif /* JERRY_LINE_INFO */ + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); +#endif /* JERRY_MODULE_SYSTEM */ + + if (declaration_type != LEXER_KEYW_VAR && context_p->token.keyword_type == LEXER_KEYW_LET) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED); + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_ASSIGN) + { +#if JERRY_LINE_INFO + parser_line_info_append (context_p, ident_line_counter, ident_column_counter); +#endif /* JERRY_LINE_INFO */ + + uint16_t index = context_p->lit_object.index; + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + cbc_opcode_t opcode = CBC_ASSIGN_SET_IDENT; + + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + uint16_t name_index = scanner_save_literal (context_p, index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, index, 0); + } + + if (declaration_type != LEXER_KEYW_VAR && (index < PARSER_REGISTER_START)) + { + opcode = CBC_INIT_LET; + + if (scanner_literal_is_created (context_p, index)) + { + opcode = CBC_ASSIGN_LET_CONST; + } + else if (declaration_type == LEXER_KEYW_CONST) + { + opcode = CBC_INIT_CONST; + } + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, index); + } + else if (declaration_type == LEXER_KEYW_LET) + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + + uint16_t index = context_p->lit_object.index; + cbc_opcode_t opcode = CBC_MOV_IDENT; + + if (index < PARSER_REGISTER_START) + { + opcode = (scanner_literal_is_created (context_p, index) ? CBC_ASSIGN_LET_CONST : CBC_INIT_LET); + } + + parser_emit_cbc_literal (context_p, (uint16_t) opcode, index); + } + else if (declaration_type == LEXER_KEYW_CONST) + { + parser_raise_error (context_p, PARSER_ERR_MISSING_ASSIGN_AFTER_CONST); + } + } + + if (context_p->token.type != LEXER_COMMA) + { + break; + } + } + +#if JERRY_MODULE_SYSTEM + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT); +#endif /* JERRY_MODULE_SYSTEM */ +} /* parser_parse_var_statement */ + +/** + * Parse function statement. + */ +static void +parser_parse_function_statement (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FUNCTION); + + bool is_single_statement = (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) != 0; + + if (JERRY_UNLIKELY (is_single_statement)) + { + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_IF || context_p->stack_top_uint8 == PARSER_STATEMENT_ELSE) + { + /* There must be a parser error later if this check fails. */ + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + parser_push_block_context (context_p, true); + } + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_LABEL) + { + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t) + 1); + + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + + if (type == PARSER_STATEMENT_LABEL) + { + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t) + 1); + continue; + } + + if (parser_statement_flags[type] & PARSER_STATM_HAS_BLOCK) + { + break; + } + + parser_raise_error (context_p, PARSER_ERR_LABELLED_FUNC_NOT_IN_BLOCK); + } + } + else + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } + } +#if JERRY_FUNCTION_TO_STRING + if (!(context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)) + { + context_p->function_start_p = context_p->token.lit_location.char_p; + } +#endif /* JERRY_FUNCTION_TO_STRING */ + + bool is_generator_function = false; + + if (lexer_consume_generator (context_p)) + { + if (is_single_statement) + { + parser_raise_error (context_p, PARSER_ERR_GENERATOR_IN_SINGLE_STATEMENT_POS); + } + is_generator_function = true; + } + + lexer_expect_identifier (context_p, LEXER_NEW_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED) + { + parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED); + } + + uint16_t function_name_index = context_p->lit_object.index; + +#if JERRY_MODULE_SYSTEM + parser_module_append_export_name (context_p); + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT); +#endif /* JERRY_MODULE_SYSTEM */ + + uint32_t status_flags = PARSER_FUNCTION_CLOSURE; + + if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS) + { + status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + + if (is_generator_function) + { + status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC) + { + status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD; + } + + JERRY_ASSERT (context_p->scope_stack_top >= 2); + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top - 2; + + uint16_t literal_index = context_p->lit_object.index; + + while (literal_index != scope_stack_p->map_from) + { + scope_stack_p--; + + JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p); + } + + JERRY_ASSERT (scope_stack_p[1].map_from == PARSER_SCOPE_STACK_FUNC); + + if (!(context_p->status_flags & PARSER_IS_STRICT) + && (scope_stack_p >= context_p->scope_stack_p + context_p->scope_stack_global_end)) + { + bool copy_value = true; + + parser_scope_stack_t *stack_p = context_p->scope_stack_p; + + while (stack_p < scope_stack_p) + { + if (literal_index == stack_p->map_from && (stack_p->map_to & PARSER_SCOPE_STACK_NO_FUNCTION_COPY)) + { + copy_value = false; + break; + } + stack_p++; + } + + if (copy_value) + { + stack_p = context_p->scope_stack_p; + + while (stack_p < scope_stack_p) + { + if (literal_index == stack_p->map_from) + { + JERRY_ASSERT (!(stack_p->map_to & PARSER_SCOPE_STACK_NO_FUNCTION_COPY)); + + uint16_t map_to = scanner_decode_map_to (stack_p); + uint16_t opcode = ((map_to >= PARSER_REGISTER_START) ? CBC_ASSIGN_LITERAL_SET_IDENT : CBC_COPY_TO_GLOBAL); + + parser_emit_cbc_literal_value (context_p, opcode, scanner_decode_map_to (scope_stack_p), map_to); + break; + } + stack_p++; + } + + parser_flush_cbc (context_p); + } + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT)) + { + parser_pop_block_context (context_p); + } + } + + lexer_literal_t *literal_p = PARSER_GET_LITERAL ((size_t) scope_stack_p[1].map_to); + + JERRY_ASSERT ((literal_p->type == LEXER_UNUSED_LITERAL || literal_p->type == LEXER_FUNCTION_LITERAL) + && literal_p->status_flags == 0); + + ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, status_flags); + + if (literal_p->type == LEXER_FUNCTION_LITERAL) + { + ecma_bytecode_deref (literal_p->u.bytecode_p); + } + + literal_p->u.bytecode_p = compiled_code_p; + literal_p->type = LEXER_FUNCTION_LITERAL; + + parser_compiled_code_set_function_name (context_p, compiled_code_p, function_name_index, 0); + lexer_next_token (context_p); +} /* parser_parse_function_statement */ + +/** + * Parse if statement (starting part). + */ +static void +parser_parse_if_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_if_else_statement_t if_statement; + + parser_parse_enclosed_expr (context_p); + + parser_emit_cbc_forward_branch (context_p, CBC_BRANCH_IF_FALSE_FORWARD, &if_statement.branch); + + parser_stack_push (context_p, &if_statement, sizeof (parser_if_else_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_IF); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_if_statement_start */ + +/** + * Parse if statement (ending part). + * + * @return true - if parsing an 'else' statement + * false - otherwise + */ +static bool +parser_parse_if_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_if_else_statement_t if_statement; + parser_if_else_statement_t else_statement; + parser_stack_iterator_t iterator; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_IF); + + if (context_p->token.type != LEXER_KEYW_ELSE) + { + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &if_statement, sizeof (parser_if_else_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_branch_to_current_position (context_p, &if_statement.branch); + + return false; + } + + parser_stack_change_last_uint8 (context_p, PARSER_STATEMENT_ELSE); + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &if_statement, sizeof (parser_if_else_statement_t)); + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &else_statement.branch); + + parser_set_branch_to_current_position (context_p, &if_statement.branch); + + parser_stack_iterator_write (&iterator, &else_statement, sizeof (parser_if_else_statement_t)); + + lexer_next_token (context_p); + return true; +} /* parser_parse_if_statement_end */ + +/** + * Parse with statement (starting part). + */ +static void +parser_parse_with_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_with_statement_t with_statement; + + if (context_p->status_flags & PARSER_IS_STRICT) + { + parser_raise_error (context_p, PARSER_ERR_WITH_NOT_ALLOWED); + } + + parser_parse_enclosed_expr (context_p); + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + uint8_t inside_with = (context_p->status_flags & PARSER_INSIDE_WITH) != 0; + + context_p->status_flags |= PARSER_INSIDE_WITH; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_WITH_CREATE_CONTEXT, &with_statement.branch); + + parser_stack_push (context_p, &with_statement, sizeof (parser_with_statement_t)); + parser_stack_push_uint8 (context_p, inside_with); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_WITH); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_with_statement_start */ + +/** + * Parse with statement (ending part). + */ +static void +parser_parse_with_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_with_statement_t with_statement; + + JERRY_ASSERT (context_p->status_flags & PARSER_INSIDE_WITH); + + parser_stack_pop_uint8 (context_p); + + if (!context_p->stack_top_uint8) + { + context_p->status_flags &= (uint32_t) ~PARSER_INSIDE_WITH; + } + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &with_statement, sizeof (parser_with_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_flush_cbc (context_p); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_set_branch_to_current_position (context_p, &with_statement.branch); +} /* parser_parse_with_statement_end */ + +/** + * Parse do-while statement (ending part). + */ +static void +parser_parse_do_while_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_DO_WHILE); + + if (context_p->token.type != LEXER_KEYW_WHILE) + { + parser_raise_error (context_p, PARSER_ERR_WHILE_EXPECTED); + } + + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p); + + parser_parse_enclosed_expr (context_p); + + if (context_p->last_cbc_opcode != CBC_PUSH_FALSE) + { + cbc_opcode_t opcode = CBC_BRANCH_IF_TRUE_BACKWARD; + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_FALSE_BACKWARD; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TRUE) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_JUMP_BACKWARD; + } + + parser_do_while_statement_t do_while_statement; + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &do_while_statement, sizeof (parser_do_while_statement_t)); + + parser_emit_cbc_backward_branch (context_p, (uint16_t) opcode, do_while_statement.start_offset); + } + else + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + + parser_stack_pop (context_p, NULL, 1 + sizeof (parser_loop_statement_t) + sizeof (parser_do_while_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); +} /* parser_parse_do_while_statement_end */ + +/** + * Parse while statement (starting part). + */ +static void +parser_parse_while_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_while_statement_t while_statement; + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_WHILE); + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_WHILE); + + if (context_p->next_scanner_info_p->source_p != context_p->source_p) + { + /* The prescanner couldn't find the end of the while condition. */ + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + JERRY_ASSERT (context_p->token.type != LEXER_RIGHT_PAREN); + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &while_statement.branch); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + while_statement.start_offset = context_p->byte_code_size; + scanner_get_location (&while_statement.condition_location, context_p); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &while_statement, sizeof (parser_while_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_WHILE); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_while_statement_start */ + +/** + * Parse while statement (ending part). + */ +static void JERRY_ATTR_NOINLINE +parser_parse_while_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_while_statement_t while_statement; + parser_loop_statement_t loop; + lexer_token_t current_token; + scanner_location_t location; + cbc_opcode_t opcode; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_WHILE); + + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &while_statement, sizeof (parser_while_statement_t)); + + scanner_get_location (&location, context_p); + current_token = context_p->token; + + parser_set_branch_to_current_position (context_p, &while_statement.branch); + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + scanner_set_location (context_p, &while_statement.condition_location); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR); + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + opcode = CBC_BRANCH_IF_TRUE_BACKWARD; + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_FALSE_BACKWARD; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TRUE) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_JUMP_BACKWARD; + } + + parser_stack_pop (context_p, NULL, 1 + sizeof (parser_loop_statement_t) + sizeof (parser_while_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_emit_cbc_backward_branch (context_p, (uint16_t) opcode, while_statement.start_offset); + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + + /* Calling scanner_seek is unnecessary because all + * info blocks inside the while statement should be processed. */ + scanner_set_location (context_p, &location); + context_p->token = current_token; +} /* parser_parse_while_statement_end */ + +/** + * Check whether the opcode is a valid LeftHandSide expression + * and convert it back to an assignment. + * + * @return the compatible assignment opcode + */ +static uint16_t +parser_check_left_hand_side_expression (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode to check */ +{ + if (opcode == CBC_PUSH_LITERAL && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + return CBC_ASSIGN_SET_IDENT; + } + else if (opcode == CBC_PUSH_PROP) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + return CBC_ASSIGN; + } + else if (opcode == CBC_PUSH_PROP_LITERAL) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + return CBC_ASSIGN_PROP_LITERAL; + } + else if (opcode == CBC_PUSH_PROP_LITERAL_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + return CBC_ASSIGN; + } + else if (opcode == CBC_PUSH_PROP_THIS_LITERAL) + { + context_p->last_cbc_opcode = CBC_PUSH_THIS_LITERAL; + return CBC_ASSIGN; + } + else + { + /* Invalid LeftHandSide expression. */ + parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_FOR_LOOP); + return CBC_ASSIGN; + } + + return opcode; +} /* parser_check_left_hand_side_expression */ + +/** + * Parse for statement (starting part). + */ +static void +parser_parse_for_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FOR); + lexer_next_token (context_p); + bool is_for_await = false; + + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + if (JERRY_UNLIKELY (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD); + } + lexer_next_token (context_p); + is_for_await = true; + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + if (context_p->token.type == LEXER_LITERAL && context_p->token.keyword_type == LEXER_KEYW_AWAIT + && !(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + parser_raise_error (context_p, PARSER_ERR_FOR_AWAIT_NO_ASYNC); + } + + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + parser_for_in_of_statement_t for_in_of_statement; + scanner_location_t start_location, end_location; + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_IN + || context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_OF); + + bool is_for_in = (context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_IN); + end_location = ((scanner_location_info_t *) context_p->next_scanner_info_p)->location; + + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + + scanner_get_location (&start_location, context_p); + lexer_next_token (context_p); + + uint8_t token_type = LEXER_EOS; + bool has_context = false; + + if (context_p->token.type == LEXER_KEYW_VAR || context_p->token.type == LEXER_KEYW_LET + || context_p->token.type == LEXER_KEYW_CONST) + { + token_type = context_p->token.type; + has_context = context_p->next_scanner_info_p->source_p == context_p->source_p; + JERRY_ASSERT (!has_context || context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + scanner_get_location (&start_location, context_p); + + /* TODO: remove this after the pre-scanner supports strict mode detection. */ + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + else if (context_p->token.type == LEXER_LITERAL && lexer_token_is_let (context_p)) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + else + { + token_type = LEXER_KEYW_LET; + has_context = (context_p->next_scanner_info_p->source_p == context_p->source_p); + scanner_get_location (&start_location, context_p); + } + } + + if (has_context) + { + has_context = parser_push_block_context (context_p, true); + } + + scanner_set_location (context_p, &end_location); + + /* The length of both 'in' and 'of' is two. */ + const uint8_t *source_end_p = context_p->source_p - 2; + + scanner_seek (context_p); + + if (is_for_in && is_for_await) + { + context_p->token.line = context_p->line; + context_p->token.column = context_p->column - 2; + parser_raise_error (context_p, PARSER_ERR_FOR_AWAIT_NO_OF); + } + + lexer_next_token (context_p); + int options = is_for_in ? PARSE_EXPR : PARSE_EXPR_NO_COMMA; + parser_parse_expression (context_p, options); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, + is_for_in ? PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION : PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + cbc_ext_opcode_t init_opcode = CBC_EXT_FOR_IN_INIT; + + if (!is_for_in) + { + init_opcode = is_for_await ? CBC_EXT_FOR_AWAIT_OF_INIT : CBC_EXT_FOR_OF_INIT; + } + + parser_emit_cbc_ext_forward_branch (context_p, init_opcode, &for_in_of_statement.branch); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + for_in_of_statement.start_offset = context_p->byte_code_size; + + if (has_context) + { + parser_emit_cbc_ext (context_p, CBC_EXT_CLONE_CONTEXT); + } + + /* The expression parser must not read the 'in' or 'of' tokens. */ + scanner_get_location (&end_location, context_p); + scanner_set_location (context_p, &start_location); + + const uint8_t *original_source_end_p = context_p->source_end_p; + context_p->source_end_p = source_end_p; + scanner_seek (context_p); + + if (token_type == LEXER_EOS) + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + token_type = context_p->token.type; + } + } + + switch (token_type) + { + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + case LEXER_KEYW_VAR: + { + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)) + { + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); + + parser_pattern_flags_t flags = (parser_pattern_flags_t ) ((unsigned int) PARSER_PATTERN_BINDING | (unsigned int) PARSER_PATTERN_TARGET_ON_STACK); + + if (context_p->next_scanner_info_p->source_p == (context_p->source_p + 1)) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS); + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_HAS_REST_ELEMENT); + } + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + } + + if (token_type == LEXER_KEYW_LET) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_LET); + } + else if (token_type == LEXER_KEYW_CONST) + { + flags = (parser_pattern_flags_t) ((int) flags | (int) PARSER_PATTERN_CONST); + } + + parser_parse_initializer_by_next_char (context_p, flags); + break; + } + + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + + if (context_p->token.keyword_type == LEXER_KEYW_LET && token_type != LEXER_KEYW_VAR) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING); + } + + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + uint16_t literal_index = context_p->lit_object.index; + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_ASSIGN) + { + if ((context_p->status_flags & PARSER_IS_STRICT) || !is_for_in) + { + parser_raise_error (context_p, PARSER_ERR_FOR_IN_OF_DECLARATION); + } + parser_branch_t branch; + + /* Initialiser is never executed. */ + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &branch); + lexer_next_token (context_p); + parser_parse_expression_statement (context_p, PARSE_EXPR_NO_COMMA); + parser_set_branch_to_current_position (context_p, &branch); + } + + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); +#ifndef JERRY_NDEBUG + if (literal_index < PARSER_REGISTER_START && has_context + && !scanner_literal_is_created (context_p, literal_index)) + { + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR; + } +#endif /* !JERRY_NDEBUG */ + + uint16_t opcode = (has_context ? CBC_ASSIGN_LET_CONST : CBC_ASSIGN_SET_IDENT); + parser_emit_cbc_literal (context_p, opcode, literal_index); + break; + } + case LEXER_LEFT_BRACE: + case LEXER_LEFT_SQUARE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS + && (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_DESTRUCTURING_FOR)) + { + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); + + uint32_t flags = PARSER_PATTERN_TARGET_ON_STACK; + + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + + scanner_release_next (context_p, sizeof (scanner_info_t)); + parser_parse_initializer (context_p, (parser_pattern_flags_t) flags); + /* Pop the value returned by GET_NEXT. */ + parser_emit_cbc (context_p, CBC_POP); + break; + } + /* FALLTHRU */ + } + default: + { + uint16_t opcode; + + parser_parse_expression (context_p, PARSE_EXPR_LEFT_HAND_SIDE); + + opcode = context_p->last_cbc_opcode; + + /* The CBC_EXT_FOR_IN_CREATE_CONTEXT flushed the opcode combiner. */ + JERRY_ASSERT (opcode != CBC_PUSH_TWO_LITERALS && opcode != CBC_PUSH_THREE_LITERALS); + + opcode = parser_check_left_hand_side_expression (context_p, opcode); + + parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT : CBC_EXT_FOR_OF_GET_NEXT); + parser_flush_cbc (context_p); + + context_p->last_cbc_opcode = opcode; + break; + } + } + + if (context_p->token.type != LEXER_EOS) + { + parser_raise_error (context_p, is_for_in ? PARSER_ERR_IN_EXPECTED : PARSER_ERR_OF_EXPECTED); + } + + parser_flush_cbc (context_p); + scanner_set_location (context_p, &end_location); + context_p->source_end_p = original_source_end_p; + lexer_next_token (context_p); + + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &for_in_of_statement, sizeof (parser_for_in_of_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + + uint8_t for_type = PARSER_STATEMENT_FOR_IN; + + if (!is_for_in) + { + for_type = is_for_await ? PARSER_STATEMENT_FOR_AWAIT_OF : PARSER_STATEMENT_FOR_OF; + } + + parser_stack_push_uint8 (context_p, for_type); + parser_stack_iterator_init (context_p, &context_p->last_statement); + return; + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_SEMICOLON) + { + const uint8_t *source_p = context_p->source_p; + + switch (context_p->token.type) + { + case LEXER_LITERAL: + { + if (!lexer_token_is_let (context_p)) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + + /* FALLTHRU */ + } + case LEXER_KEYW_LET: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type != SCANNER_TYPE_BLOCK) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + + context_p->token.type = LEXER_KEYW_LET; + + /* FALLTHRU */ + } + case LEXER_KEYW_CONST: + { + if (context_p->next_scanner_info_p->source_p == source_p) + { + parser_push_block_context (context_p, true); + } + /* FALLTHRU */ + } + case LEXER_KEYW_VAR: + { + parser_parse_var_statement (context_p); + break; + } + default: + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + } + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + } + + if (is_for_await) + { + parser_raise_error (context_p, PARSER_ERR_FOR_AWAIT_NO_OF); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p + || context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR); + + if (context_p->next_scanner_info_p->source_p != context_p->source_p + || ((scanner_for_info_t *) context_p->next_scanner_info_p)->end_location.source_p == NULL) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + /* Even though the scanning is failed, there might be valid statements + * inside the for statement which depend on scanner info blocks. */ + scanner_release_next (context_p, sizeof (scanner_for_info_t)); + } + + /* The prescanner couldn't find the second semicolon or the closing paranthesis. */ + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_expression_statement (context_p, PARSE_EXPR); + + JERRY_ASSERT (context_p->token.type != LEXER_RIGHT_PAREN); + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + parser_for_statement_t for_statement; + scanner_for_info_t *for_info_p = (scanner_for_info_t *) context_p->next_scanner_info_p; + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &for_statement.branch); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + for_statement.start_offset = context_p->byte_code_size; + scanner_get_location (&for_statement.condition_location, context_p); + for_statement.expression_location = for_info_p->expression_location; + + scanner_set_location (context_p, &for_info_p->end_location); + scanner_release_next (context_p, sizeof (scanner_for_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &for_statement, sizeof (parser_for_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_FOR); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_for_statement_start */ + +/** + * Parse for statement (ending part). + */ +static void JERRY_ATTR_NOINLINE +parser_parse_for_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_for_statement_t for_statement; + parser_loop_statement_t loop; + lexer_token_t current_token; + scanner_location_t location; + cbc_opcode_t opcode; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_FOR); + + parser_stack_iterator_t iterator; + parser_stack_iterator_init (context_p, &iterator); + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &for_statement, sizeof (parser_for_statement_t)); + + bool has_block_context = false; + uint8_t next_statement_type; + + parser_stack_iterator_skip (&iterator, sizeof (parser_for_statement_t)); + parser_stack_iterator_read (&iterator, &next_statement_type, 1); + + if (next_statement_type == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + has_block_context = true; + } + + scanner_get_location (&location, context_p); + current_token = context_p->token; + + scanner_set_location (context_p, &for_statement.expression_location); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + if (has_block_context) + { + parser_emit_cbc_ext (context_p, CBC_EXT_CLONE_FULL_CONTEXT); + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + } + + parser_set_branch_to_current_position (context_p, &for_statement.branch); + + scanner_set_location (context_p, &for_statement.condition_location); + scanner_seek (context_p); + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_SEMICOLON) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + + opcode = CBC_BRANCH_IF_TRUE_BACKWARD; + if (context_p->last_cbc_opcode == CBC_LOGICAL_NOT) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_BRANCH_IF_FALSE_BACKWARD; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TRUE) + { + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + opcode = CBC_JUMP_BACKWARD; + } + } + else + { + opcode = CBC_JUMP_BACKWARD; + } + + parser_stack_pop (context_p, NULL, 1 + sizeof (parser_loop_statement_t) + sizeof (parser_for_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_emit_cbc_backward_branch (context_p, (uint16_t) opcode, for_statement.start_offset); + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + parser_pop_block_context (context_p); + } + + /* Calling scanner_seek is unnecessary because all + * info blocks inside the for statement should be processed. */ + scanner_set_location (context_p, &location); + context_p->token = current_token; +} /* parser_parse_for_statement_end */ + +/** + * Parse switch statement (starting part). + */ +static void JERRY_ATTR_NOINLINE +parser_parse_switch_statement_start (parser_context_t *context_p) /**< context */ +{ + parser_switch_statement_t switch_statement; + parser_loop_statement_t loop; + parser_stack_iterator_t iterator; + scanner_location_t start_location; + bool switch_case_was_found; + bool default_case_was_found; + parser_branch_node_t *case_branches_p = NULL; + + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_SWITCH); + + parser_parse_enclosed_expr (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + + if (context_p->next_scanner_info_p->source_p == context_p->source_p - 1) + { + parser_push_block_context (context_p, true); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_SWITCH); + + scanner_case_info_t *case_info_p = ((scanner_switch_info_t *) context_p->next_scanner_info_p)->case_p; + scanner_set_active (context_p); + + if (case_info_p == NULL) + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + scanner_release_active (context_p, sizeof (scanner_switch_info_t)); + + parser_emit_cbc (context_p, CBC_POP); + parser_flush_cbc (context_p); + + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK); + parser_stack_iterator_init (context_p, &context_p->last_statement); + return; + } + + parser_raise_error (context_p, PARSER_ERR_INVALID_SWITCH); + } + + scanner_get_location (&start_location, context_p); + + /* The reason of using an iterator is error management. If an error + * occures, parser_free_jumps() free all data. However, the branches + * created by parser_emit_cbc_forward_branch_item() would not be freed. + * To free these branches, the current switch data is always stored + * on the stack. If any change happens, this data is updated. Updates + * are done using the iterator. */ + + switch_statement.branch_list_p = NULL; + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &switch_statement, sizeof (parser_switch_statement_t)); + parser_stack_iterator_init (context_p, &iterator); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_SWITCH); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + switch_case_was_found = false; + default_case_was_found = false; + + do + { + scanner_set_location (context_p, &case_info_p->location); + scanner_seek (context_p); + case_info_p = case_info_p->next_p; + + /* The last letter of case and default is 'e' and 't' respectively. */ + JERRY_ASSERT (context_p->source_p[-1] == LIT_CHAR_LOWERCASE_E || context_p->source_p[-1] == LIT_CHAR_LOWERCASE_T); + + bool is_default = context_p->source_p[-1] == LIT_CHAR_LOWERCASE_T; + lexer_next_token (context_p); + + if (is_default) + { + if (default_case_was_found) + { + parser_raise_error (context_p, PARSER_ERR_MULTIPLE_DEFAULTS_NOT_ALLOWED); + } + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + default_case_was_found = true; + continue; + } + + switch_case_was_found = true; + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->token.type != LEXER_COLON) + { + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + uint16_t opcode = CBC_BRANCH_IF_STRICT_EQUAL; + + if (case_info_p == NULL + || (case_info_p->next_p == NULL && case_info_p->location.source_p[-1] == LIT_CHAR_LOWERCASE_T)) + { + /* There are no more 'case' statements in the switch. */ + parser_emit_cbc (context_p, CBC_STRICT_EQUAL); + opcode = CBC_BRANCH_IF_TRUE_FORWARD; + } + + parser_branch_node_t *new_case_p = parser_emit_cbc_forward_branch_item (context_p, opcode, NULL); + + if (case_branches_p == NULL) + { + switch_statement.branch_list_p = new_case_p; + parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + } + else + { + case_branches_p->next_p = new_case_p; + } + + case_branches_p = new_case_p; + } while (case_info_p != NULL); + + JERRY_ASSERT (switch_case_was_found || default_case_was_found); + + if (!switch_case_was_found) + { + /* There was no case statement, so the expression result + * of the switch must be popped from the stack */ + parser_emit_cbc (context_p, CBC_POP); + } + + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &switch_statement.default_branch); + parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + if (!default_case_was_found) + { + parser_stack_change_last_uint8 (context_p, PARSER_STATEMENT_SWITCH_NO_DEFAULT); + } + + scanner_release_switch_cases (((scanner_switch_info_t *) context_p->active_scanner_info_p)->case_p); + scanner_release_active (context_p, sizeof (scanner_switch_info_t)); + + scanner_set_location (context_p, &start_location); + scanner_seek (context_p); + lexer_next_token (context_p); +} /* parser_parse_switch_statement_start */ + +/** + * Parse try statement (ending part). + */ +static void +parser_parse_try_statement_end (parser_context_t *context_p) /**< context */ +{ + parser_try_statement_t try_statement; + parser_stack_iterator_t iterator; + + JERRY_ASSERT (context_p->stack_top_uint8 == PARSER_STATEMENT_TRY); + + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &try_statement, sizeof (parser_try_statement_t)); + + context_p->scope_stack_top = try_statement.scope_stack_top; + context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top; + + lexer_next_token (context_p); + + if (try_statement.type == parser_finally_block) + { + parser_flush_cbc (context_p); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_set_branch_to_current_position (context_p, &try_statement.branch); + } + else + { + parser_set_branch_to_current_position (context_p, &try_statement.branch); + + if (try_statement.type == parser_catch_block) + { + if (context_p->token.type != LEXER_KEYW_FINALLY) + { + parser_flush_cbc (context_p); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + parser_flush_cbc (context_p); + + try_statement.type = parser_finally_block; + } + } + else + { + JERRY_ASSERT (try_statement.type == parser_try_block); + + if (context_p->token.type != LEXER_KEYW_CATCH && context_p->token.type != LEXER_KEYW_FINALLY) + { + parser_raise_error (context_p, PARSER_ERR_CATCH_FINALLY_EXPECTED); + } + } + } + + if (try_statement.type == parser_finally_block) + { + parser_stack_pop (context_p, NULL, (uint32_t) (sizeof (parser_try_statement_t) + 1)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + return; + } + + if (context_p->token.type == LEXER_KEYW_CATCH) + { + lexer_next_token (context_p); + + try_statement.type = parser_catch_block; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_CATCH, &try_statement.branch); + + try_statement.scope_stack_top = context_p->scope_stack_top; + try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top; + +#ifndef JERRY_NDEBUG + bool block_found = false; +#endif /* !JERRY_NDEBUG */ + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); +#ifndef JERRY_NDEBUG + block_found = true; +#endif /* !JERRY_NDEBUG */ + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV); + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE)) + { + parser_pattern_flags_t flags = (parser_pattern_flags_t) ((unsigned int) PARSER_PATTERN_BINDING | (unsigned int) PARSER_PATTERN_TARGET_ON_STACK | (unsigned int) PARSER_PATTERN_LET); + + parser_parse_initializer_by_next_char (context_p, flags); + } + else + { + lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL); + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + uint16_t literal_index = context_p->lit_object.index; + parser_emit_cbc_literal (context_p, + (literal_index >= PARSER_REGISTER_START) ? CBC_ASSIGN_SET_IDENT : CBC_ASSIGN_LET_CONST, + literal_index); + + lexer_next_token (context_p); + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (block_found); +#endif /* !JERRY_NDEBUG */ + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + } + else if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_emit_cbc (context_p, CBC_POP); + } + else + { + parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED); + } + + parser_flush_cbc (context_p); + } + else + { + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FINALLY); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + try_statement.type = parser_finally_block; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_FINALLY, &try_statement.branch); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV); + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + } + } + + lexer_next_token (context_p); + parser_stack_iterator_write (&iterator, &try_statement, sizeof (parser_try_statement_t)); +} /* parser_parse_try_statement_end */ + +/** + * Parse default statement. + */ +static void +parser_parse_default_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + parser_switch_statement_t switch_statement; + + if (context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH + && context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH_NO_DEFAULT) + { + parser_raise_error (context_p, PARSER_ERR_DEFAULT_NOT_IN_SWITCH); + } + + lexer_next_token (context_p); + /* Already checked in parser_parse_switch_statement_start. */ + JERRY_ASSERT (context_p->token.type == LEXER_COLON); + lexer_next_token (context_p); + + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1 + sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + parser_set_branch_to_current_position (context_p, &switch_statement.default_branch); +} /* parser_parse_default_statement */ + +/** + * Parse case statement. + */ +static void +parser_parse_case_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + parser_switch_statement_t switch_statement; + parser_branch_node_t *branch_p; + + if (context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH + && context_p->stack_top_uint8 != PARSER_STATEMENT_SWITCH_NO_DEFAULT) + { + parser_raise_error (context_p, PARSER_ERR_CASE_NOT_IN_SWITCH); + } + + if (context_p->next_scanner_info_p->source_p != context_p->source_p) + { + lexer_next_token (context_p); + + parser_parse_expression (context_p, PARSE_EXPR); + + JERRY_ASSERT (context_p->token.type != LEXER_COLON); + parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED); + } + + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CASE); + + scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location); + scanner_release_next (context_p, sizeof (scanner_location_info_t)); + scanner_seek (context_p); + lexer_next_token (context_p); + + parser_stack_iterator_init (context_p, &iterator); + parser_stack_iterator_skip (&iterator, 1 + sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + /* Free memory after the case statement is found. */ + + branch_p = switch_statement.branch_list_p; + JERRY_ASSERT (branch_p != NULL); + switch_statement.branch_list_p = branch_p->next_p; + parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + + parser_set_branch_to_current_position (context_p, &branch_p->branch); + parser_free (branch_p, sizeof (parser_branch_node_t)); +} /* parser_parse_case_statement */ + +/** + * Parse break statement. + */ +static void +parser_parse_break_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + cbc_opcode_t opcode = CBC_JUMP_FORWARD; + + lexer_next_token (context_p); + parser_stack_iterator_init (context_p, &iterator); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + /* The label with the same name is searched on the stack. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BREAK_LABEL); + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + if (type == PARSER_STATEMENT_LABEL) + { + parser_label_statement_t label_statement; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label_statement, sizeof (parser_label_statement_t)); + + if (lexer_current_is_literal (context_p, &label_statement.label_ident)) + { + label_statement.break_list_p = + parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, label_statement.break_list_p); + parser_stack_iterator_write (&iterator, &label_statement, sizeof (parser_label_statement_t)); + lexer_next_token (context_p); + return; + } + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + } + else + { + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } + } + } + + /* The first switch or loop statement is searched. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_BREAK); + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + if (parser_statement_flags[type] & PARSER_STATM_BREAK_TARGET) + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + loop.branch_list_p = parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, loop.branch_list_p); + parser_stack_iterator_write (&iterator, &loop, sizeof (parser_loop_statement_t)); + return; + } + + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } +} /* parser_parse_break_statement */ + +/** + * Parse continue statement. + */ +static void +parser_parse_continue_statement (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + cbc_opcode_t opcode = CBC_JUMP_FORWARD; + + lexer_next_token (context_p); + parser_stack_iterator_init (context_p, &iterator); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + parser_stack_iterator_t loop_iterator; + + loop_iterator.current_p = NULL; + + /* The label with the same name is searched on the stack. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CONTINUE_LABEL); + } + + /* Only those labels are checked, whose are label of a loop. */ + if (loop_iterator.current_p != NULL && type == PARSER_STATEMENT_LABEL) + { + parser_label_statement_t label_statement; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label_statement, sizeof (parser_label_statement_t)); + + if (lexer_current_is_literal (context_p, &label_statement.label_ident)) + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&loop_iterator, 1); + parser_stack_iterator_read (&loop_iterator, &loop, sizeof (parser_loop_statement_t)); + loop.branch_list_p = parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, loop.branch_list_p); + loop.branch_list_p->branch.offset |= CBC_HIGHEST_BIT_MASK; + parser_stack_iterator_write (&loop_iterator, &loop, sizeof (parser_loop_statement_t)); + lexer_next_token (context_p); + return; + } + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + continue; + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + const bool is_private_scope = + (type == PARSER_STATEMENT_PRIVATE_SCOPE || type == PARSER_STATEMENT_PRIVATE_CONTEXT); + + if (parser_statement_flags[type] & PARSER_STATM_CONTINUE_TARGET) + { + loop_iterator = iterator; + } + else if (!is_private_scope) + { + loop_iterator.current_p = NULL; + } + + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } + } + + /* The first loop statement is searched. */ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CONTINUE); + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTINUE_TARGET) + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + loop.branch_list_p = parser_emit_cbc_forward_branch_item (context_p, (uint16_t) opcode, loop.branch_list_p); + loop.branch_list_p->branch.offset |= CBC_HIGHEST_BIT_MASK; + parser_stack_iterator_write (&iterator, &loop, sizeof (parser_loop_statement_t)); + return; + } + + if (parser_statement_flags[type] & PARSER_STATM_CONTEXT_BREAK) + { + opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT; + } + + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } +} /* parser_parse_continue_statement */ + +#if JERRY_MODULE_SYSTEM +/** + * Parse import statement. + * Note: See 15.2.2 + */ +static void +parser_parse_import_statement (parser_context_t *context_p) /**< parser context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_IMPORT); + JERRY_ASSERT (context_p->module_names_p == NULL); + + if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_PAREN, LIT_CHAR_DOT)) + { + if (context_p->status_flags & PARSER_IS_FUNCTION) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + return; + } + + parser_parse_block_expression (context_p, PARSE_EXPR); + return; + } + + parser_module_check_request_place (context_p); + lexer_next_token (context_p); + + /* Check for a ModuleSpecifier*/ + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_STRING_LITERAL) + { + if (!(context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_MULTIPLY + || (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL))) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED); + } + + if (context_p->token.type == LEXER_LITERAL) + { + /* Handle ImportedDefaultBinding */ + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + ecma_string_t *local_name_p = parser_new_ecma_string_from_literal (context_p->lit_object.literal_p); + + if (parser_module_check_duplicate_import (context_p, local_name_p)) + { + ecma_deref_ecma_string (local_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING); + } + + ecma_string_t *import_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT); + parser_module_add_names_to_node (context_p, import_name_p, local_name_p); + + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + if (context_p->token.type != LEXER_MULTIPLY && context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED); + } + } + else if (!lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_FROM_COMMA_EXPECTED); + } + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + /* NameSpaceImport */ + lexer_next_token (context_p); + if (!lexer_token_is_identifier (context_p, "as", 2)) + { + parser_raise_error (context_p, PARSER_ERR_AS_EXPECTED); + } + + lexer_next_token (context_p); + if (context_p->token.type != LEXER_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + ecma_string_t *local_name_p = parser_new_ecma_string_from_literal (context_p->lit_object.literal_p); + + if (parser_module_check_duplicate_import (context_p, local_name_p)) + { + ecma_deref_ecma_string (local_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING); + } + + ecma_string_t *import_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR); + + parser_module_add_names_to_node (context_p, import_name_p, local_name_p); + ecma_deref_ecma_string (local_name_p); + ecma_deref_ecma_string (import_name_p); + + lexer_next_token (context_p); + } + else if (context_p->token.type == LEXER_LEFT_BRACE) + { + /* Handle NamedImports */ + parser_module_parse_import_clause (context_p); + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED); + } + lexer_next_token (context_p); + } + + parser_module_handle_module_specifier (context_p, NULL); +} /* parser_parse_import_statement */ + +/** + * Parse export statement. + * + * @return true - if function of class statement was found + * false - otherwise + */ +static bool +parser_parse_export_statement (parser_context_t *context_p) /**< context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_EXPORT); + JERRY_ASSERT (context_p->module_names_p == NULL); + + parser_module_check_request_place (context_p); + + bool consume_last_statement = false; + + lexer_next_token (context_p); + switch (context_p->token.type) + { + case LEXER_KEYW_DEFAULT: + { + scanner_location_t location; + scanner_get_location (&location, context_p); + + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LITERAL && lexer_token_is_async (context_p) + && context_p->next_scanner_info_p->source_p == context_p->source_p + && context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION) + { +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + lexer_next_token (context_p); + } + + if (context_p->token.type == LEXER_KEYW_CLASS) + { + context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC; + parser_parse_class (context_p, true); + consume_last_statement = true; + } + else if (context_p->token.type == LEXER_KEYW_FUNCTION) + { + context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC; + parser_parse_function_statement (context_p); + consume_last_statement = true; + } + else + { + /* Assignment expression */ + scanner_set_location (context_p, &location); + + /* 15.2.3.5 Use the synthetic name '*default*' as the identifier. */ + lexer_construct_literal_object (context_p, &lexer_default_literal, lexer_default_literal.type); + + context_p->token.lit_location.type = LEXER_IDENT_LITERAL; + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + + /* Do not overwrite this identifier. */ + context_p->status_flags &= (uint32_t) ~PARSER_MODULE_STORE_IDENT; + context_p->module_identifier_lit_p = context_p->lit_object.literal_p; + + /* Fake an assignment to the default identifier */ + context_p->token.type = LEXER_ASSIGN; + + parser_parse_expression_statement (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_HAS_LITERAL); + } + + ecma_string_t *name_p = parser_new_ecma_string_from_literal (context_p->module_identifier_lit_p); + + ecma_string_t *export_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT); + + if (parser_module_check_duplicate_export (context_p, export_name_p)) + { + ecma_deref_ecma_string (name_p); + ecma_deref_ecma_string (export_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + parser_module_add_names_to_node (context_p, export_name_p, name_p); + ecma_deref_ecma_string (name_p); + ecma_deref_ecma_string (export_name_p); + break; + } + case LEXER_MULTIPLY: + { + lexer_next_token (context_p); + + ecma_module_node_t **target_node_list_p = &(JERRY_CONTEXT (module_current_p)->star_exports_p); + + if (lexer_token_is_identifier (context_p, "as", 2)) + { + target_node_list_p = &(JERRY_CONTEXT (module_current_p)->indirect_exports_p); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL); + + lexer_literal_t *literal_p = PARSER_GET_LITERAL (context_p->lit_object.index); + ecma_string_t *export_name_p = parser_new_ecma_string_from_literal (literal_p); + + if (parser_module_check_duplicate_export (context_p, export_name_p)) + { + ecma_deref_ecma_string (export_name_p); + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER); + } + + ecma_string_t *local_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR); + parser_module_add_names_to_node (context_p, export_name_p, local_name_p); + ecma_deref_ecma_string (export_name_p); + + lexer_next_token (context_p); + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED); + } + + lexer_next_token (context_p); + parser_module_handle_module_specifier (context_p, target_node_list_p); + return false; + } + case LEXER_KEYW_VAR: + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + { + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + parser_parse_var_statement (context_p); + break; + } + case LEXER_KEYW_CLASS: + { + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + parser_parse_class (context_p, true); + consume_last_statement = true; + break; + } + case LEXER_KEYW_FUNCTION: + { + context_p->status_flags |= PARSER_MODULE_STORE_IDENT; + parser_parse_function_statement (context_p); + consume_last_statement = true; + break; + } + case LEXER_LEFT_BRACE: + { + parser_module_parse_export_clause (context_p); + + if (lexer_token_is_identifier (context_p, "from", 4)) + { + lexer_next_token (context_p); + parser_module_handle_module_specifier (context_p, &(JERRY_CONTEXT (module_current_p)->indirect_exports_p)); + return false; + } + break; + } + default: + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED); + break; + } + } + + context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC | PARSER_MODULE_STORE_IDENT); + parser_module_append_names (context_p, &(JERRY_CONTEXT (module_current_p)->local_exports_p)); + + return consume_last_statement; +} /* parser_parse_export_statement */ +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Parse label statement. + */ +static void +parser_parse_label (parser_context_t *context_p) /**< context */ +{ + parser_stack_iterator_t iterator; + parser_label_statement_t label_statement; + + parser_stack_iterator_init (context_p, &iterator); + + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + if (type == PARSER_STATEMENT_START) + { + break; + } + + if (type == PARSER_STATEMENT_LABEL) + { + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label_statement, sizeof (parser_label_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + + if (lexer_current_is_literal (context_p, &label_statement.label_ident)) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_LABEL); + } + } + else + { + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + } + } + + label_statement.label_ident = context_p->token.lit_location; + label_statement.break_list_p = NULL; + parser_stack_push (context_p, &label_statement, sizeof (parser_label_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_LABEL); + parser_stack_iterator_init (context_p, &context_p->last_statement); +} /* parser_parse_label */ + +/** + * Strict mode types for statement parsing. + */ +typedef enum +{ + PARSER_USE_STRICT_NOT_FOUND = 0, /**< 'use strict' directive is not found */ + PARSER_USE_STRICT_FOUND = 1, /**< 'use strict' directive is found but strict mode has already been enabled */ + PARSER_USE_STRICT_SET = 2, /**< strict mode is enabled after 'use strict' directive is found */ +} parser_strict_mode_type_t; + +/** + * Parse statements. + */ +void +parser_parse_statements (parser_context_t *context_p) /**< context */ +{ + /* Statement parsing cannot be nested. */ + JERRY_ASSERT (context_p->last_statement.current_p == NULL); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_START); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + while (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + lexer_lit_location_t lit_location; + parser_strict_mode_type_t strict_mode = PARSER_USE_STRICT_NOT_FOUND; + + JERRY_ASSERT (context_p->stack_depth <= 1); +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context_p->context_stack_depth == context_p->stack_depth); +#endif /* !JERRY_NDEBUG */ + + if (lexer_string_is_use_strict (context_p)) + { + strict_mode = PARSER_USE_STRICT_FOUND; + + if (!(context_p->status_flags & PARSER_IS_STRICT)) + { + /* The next token should be parsed in strict mode. */ + context_p->status_flags |= PARSER_IS_STRICT; + strict_mode = PARSER_USE_STRICT_SET; + } + } + + lit_location = context_p->token.lit_location; + lexer_next_token (context_p); + + if (!lexer_string_is_directive (context_p)) + { + /* The string is part of an expression statement. */ + if (strict_mode == PARSER_USE_STRICT_SET) + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + lexer_construct_literal_object (context_p, &lit_location, LEXER_STRING_LITERAL); + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + /* The extra_value is used for saving the token. */ + context_p->token.extra_value = context_p->token.type; + context_p->token.type = LEXER_EXPRESSION_START; + break; + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (strict_mode == PARSER_USE_STRICT_SET && context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" Note: switch to strict mode\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (strict_mode != PARSER_USE_STRICT_NOT_FOUND && (context_p->status_flags & PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT)) + { + parser_raise_error (context_p, PARSER_ERR_USE_STRICT_NOT_ALLOWED); + } + + if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + + /* The last directive prologue can be the result of the script. */ + if (!(context_p->status_flags & PARSER_IS_FUNCTION) + && (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_STRING_LITERAL)) + { + lexer_construct_literal_object (context_p, &lit_location, LEXER_STRING_LITERAL); + parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); + parser_emit_cbc (context_p, CBC_POP_BLOCK); + parser_flush_cbc (context_p); + break; + } + } + + if (context_p->status_flags & PARSER_IS_STRICT && context_p->status_flags & PARSER_HAS_NON_STRICT_ARG) + { + parser_raise_error (context_p, PARSER_ERR_NON_STRICT_ARG_DEFINITION); + } + + while (context_p->token.type != LEXER_EOS || context_p->stack_top_uint8 != PARSER_STATEMENT_START) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context_p->stack_depth == context_p->context_stack_depth); +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (context_p->stack_top_uint8 != PARSER_STATEMENT_PRIVATE_SCOPE + && context_p->stack_top_uint8 != PARSER_STATEMENT_PRIVATE_CONTEXT); + +#if JERRY_LINE_INFO + if (context_p->token.type != LEXER_SEMICOLON && context_p->token.type != LEXER_LEFT_BRACE + && context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_KEYW_VAR + && context_p->token.type != LEXER_KEYW_LET && context_p->token.type != LEXER_KEYW_CONST + && context_p->token.type != LEXER_KEYW_FUNCTION && context_p->token.type != LEXER_KEYW_CASE + && context_p->token.type != LEXER_KEYW_DEFAULT) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ + + switch (context_p->token.type) + { + case LEXER_SEMICOLON: + { + break; + } + + case LEXER_RIGHT_BRACE: + { + if (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) + { + parser_raise_error (context_p, PARSER_ERR_STATEMENT_EXPECTED); + } + break; + } + + case LEXER_LEFT_BRACE: + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + parser_push_block_context (context_p, false); + } + else + { + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK); + } + + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + continue; + } + + case LEXER_KEYW_VAR: + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + { + parser_parse_var_statement (context_p); + break; + } + case LEXER_KEYW_CLASS: + { + parser_validate_lexical_context (context_p); + parser_parse_class (context_p, true); + goto consume_last_statement; + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + parser_parse_import_statement (context_p); + break; + } + + case LEXER_KEYW_EXPORT: + { + if (parser_parse_export_statement (context_p)) + { + goto consume_last_statement; + } + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + + case LEXER_KEYW_FUNCTION: + { + parser_parse_function_statement (context_p); + goto consume_last_statement; + } + + case LEXER_KEYW_IF: + { + parser_parse_if_statement_start (context_p); + continue; + } + + case LEXER_KEYW_SWITCH: + { + parser_parse_switch_statement_start (context_p); + continue; + } + + case LEXER_KEYW_DO: + { + parser_do_while_statement_t do_while_statement; + parser_loop_statement_t loop; + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + do_while_statement.start_offset = context_p->byte_code_size; + loop.branch_list_p = NULL; + + parser_stack_push (context_p, &do_while_statement, sizeof (parser_do_while_statement_t)); + parser_stack_push (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_DO_WHILE); + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + continue; + } + + case LEXER_KEYW_WHILE: + { + parser_parse_while_statement_start (context_p); + continue; + } + + case LEXER_KEYW_FOR: + { + parser_parse_for_statement_start (context_p); + continue; + } + + case LEXER_KEYW_WITH: + { + parser_parse_with_statement_start (context_p); + continue; + } + + case LEXER_KEYW_TRY: + { + parser_try_statement_t try_statement; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + try_statement.type = parser_try_block; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_TRY_CREATE_CONTEXT, &try_statement.branch); + + try_statement.scope_stack_top = context_p->scope_stack_top; + try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top; + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK); + + if (scanner_is_context_needed (context_p, PARSER_CHECK_BLOCK_CONTEXT)) + { + parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV); + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + } + + parser_stack_push (context_p, &try_statement, sizeof (parser_try_statement_t)); + parser_stack_push_uint8 (context_p, PARSER_STATEMENT_TRY); + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + continue; + } + + case LEXER_KEYW_DEFAULT: + { + parser_parse_default_statement (context_p); + continue; + } + + case LEXER_KEYW_CASE: + { + parser_parse_case_statement (context_p); + continue; + } + + case LEXER_KEYW_BREAK: + { + parser_parse_break_statement (context_p); + break; + } + + case LEXER_KEYW_CONTINUE: + { + parser_parse_continue_statement (context_p); + break; + } + + case LEXER_KEYW_THROW: + { + lexer_next_token (context_p); + if (context_p->token.flags & LEXER_WAS_NEWLINE) + { + parser_raise_error (context_p, PARSER_ERR_EXPRESSION_EXPECTED); + } + parser_parse_expression (context_p, PARSE_EXPR); + parser_emit_cbc (context_p, CBC_THROW); + break; + } + + case LEXER_KEYW_RETURN: + { + if (!(context_p->status_flags & PARSER_IS_FUNCTION)) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_RETURN); + } + if (context_p->status_flags & PARSER_IS_CLASS_STATIC_BLOCK) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_RETURN); + } + + lexer_next_token (context_p); + + if ((context_p->token.flags & LEXER_WAS_NEWLINE) || context_p->token.type == LEXER_SEMICOLON + || context_p->token.type == LEXER_EOS || context_p->token.type == LEXER_RIGHT_BRACE) + { + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RETURN_UNDEFINED); + break; + } + + parser_emit_cbc (context_p, CBC_RETURN_FUNCTION_END); + break; + } + + parser_parse_expression (context_p, PARSE_EXPR); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL; + break; + } + + parser_emit_cbc (context_p, CBC_RETURN); + break; + } + + case LEXER_KEYW_DEBUGGER: + { + lexer_next_token (context_p); + break; + } + + case LEXER_LITERAL: + { + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + if (JERRY_UNLIKELY (lexer_check_next_character (context_p, LIT_CHAR_COLON))) + { + parser_parse_label (context_p); + lexer_consume_next_character (context_p); + lexer_next_token (context_p); + continue; + } + + if (JERRY_UNLIKELY (lexer_token_is_let (context_p))) + { + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION) + { + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + if (context_p->status_flags & PARSER_IS_FUNCTION) + { + parser_parse_expression_statement (context_p, PARSE_EXPR); + break; + } + + parser_parse_block_expression (context_p, PARSE_EXPR); + break; + } + + context_p->token.type = LEXER_KEYW_LET; + parser_parse_var_statement (context_p); + break; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p)) + && context_p->next_scanner_info_p->source_p == context_p->source_p) + { + bool is_statement = true; + + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION) + { + is_statement = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT) != 0; + + JERRY_ASSERT (!is_statement || (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)); + } + else + { + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION); + + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + + if (is_statement) + { + if (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM) + { + parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT); + } + +#if JERRY_FUNCTION_TO_STRING + context_p->function_start_p = context_p->token.lit_location.char_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + lexer_next_token (context_p); + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FUNCTION); + continue; + } + } + } + /* FALLTHRU */ + } + + default: + { + int options = PARSE_EXPR; + + if (context_p->token.type == LEXER_EXPRESSION_START) + { + /* Restore the token type form the extra_value. */ + context_p->token.type = context_p->token.extra_value; + options |= PARSE_EXPR_HAS_LITERAL; + } + + if (context_p->status_flags & PARSER_IS_FUNCTION) + { + parser_parse_expression_statement (context_p, options); + } + else + { + parser_parse_block_expression (context_p, options); + } + + break; + } + } + + parser_flush_cbc (context_p); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK) + { + parser_stack_pop_uint8 (context_p); + parser_stack_iterator_init (context_p, &context_p->last_statement); + lexer_next_token (context_p); + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_CONTEXT) + { + parser_pop_block_context (context_p); + lexer_next_token (context_p); + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH + || context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH_NO_DEFAULT) + { + int has_default = (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH); + parser_loop_statement_t loop; + parser_switch_statement_t switch_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_pop (context_p, &switch_statement, sizeof (parser_switch_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + JERRY_ASSERT (switch_statement.branch_list_p == NULL); + + if (!has_default) + { + parser_set_branch_to_current_position (context_p, &switch_statement.default_branch); + } + + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + lexer_next_token (context_p); + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + parser_pop_block_context (context_p); + } + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_TRY) + { + parser_parse_try_statement_end (context_p); + } + else if (context_p->stack_top_uint8 == PARSER_STATEMENT_START) + { + if (context_p->status_flags & PARSER_IS_CLOSURE) + { +#if JERRY_LINE_INFO + if (context_p->line_info_p == NULL) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + context_p->function_end_p = context_p->source_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + parser_stack_pop_uint8 (context_p); + context_p->last_statement.current_p = NULL; + /* There is no lexer_next_token here, since the + * next token belongs to the parent context. */ + return; + } + parser_raise_error (context_p, PARSER_ERR_INVALID_RIGHT_SQUARE); + } + } + else if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + else if (context_p->token.type != LEXER_EOS && !(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + +consume_last_statement: + while (true) + { + switch (context_p->stack_top_uint8) + { + case PARSER_STATEMENT_LABEL: + { + parser_label_statement_t label; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &label, sizeof (parser_label_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_breaks_to_current_position (context_p, label.break_list_p); + continue; + } + + case PARSER_STATEMENT_IF: + { + if (parser_parse_if_statement_end (context_p)) + { + break; + } + continue; + } + + case PARSER_STATEMENT_ELSE: + { + parser_if_else_statement_t else_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &else_statement, sizeof (parser_if_else_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_branch_to_current_position (context_p, &else_statement.branch); + continue; + } + + case PARSER_STATEMENT_DO_WHILE: + { + parser_parse_do_while_statement_end (context_p); + if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + continue; + } + + case PARSER_STATEMENT_WHILE: + { + parser_parse_while_statement_end (context_p); + continue; + } + + case PARSER_STATEMENT_FOR: + { + parser_parse_for_statement_end (context_p); + continue; + } + + case PARSER_STATEMENT_FOR_IN: + case PARSER_STATEMENT_FOR_OF: + case PARSER_STATEMENT_FOR_AWAIT_OF: + { + parser_for_in_of_statement_t for_in_of_statement; + parser_loop_statement_t loop; + + uint8_t for_type = context_p->stack_top_uint8; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &loop, sizeof (parser_loop_statement_t)); + parser_stack_pop (context_p, &for_in_of_statement, sizeof (parser_for_in_of_statement_t)); + parser_stack_iterator_init (context_p, &context_p->last_statement); + + parser_set_continues_to_current_position (context_p, loop.branch_list_p); + + parser_flush_cbc (context_p); + + uint16_t stack_allocation = PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + if (for_type != PARSER_STATEMENT_FOR_IN) + { + stack_allocation = (for_type == PARSER_STATEMENT_FOR_OF ? PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION + : PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION); + } + + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, stack_allocation); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, stack_allocation); +#endif /* !JERRY_NDEBUG */ + + cbc_ext_opcode_t opcode = CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT; + + if (for_type != PARSER_STATEMENT_FOR_IN) + { + opcode = (for_type == PARSER_STATEMENT_FOR_OF ? CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT + : CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT); + } + + parser_emit_cbc_ext_backward_branch (context_p, opcode, for_in_of_statement.start_offset); + + parser_set_breaks_to_current_position (context_p, loop.branch_list_p); + parser_set_branch_to_current_position (context_p, &for_in_of_statement.branch); + + if (context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_SCOPE + || context_p->stack_top_uint8 == PARSER_STATEMENT_PRIVATE_CONTEXT) + { + parser_pop_block_context (context_p); + } + + continue; + } + + case PARSER_STATEMENT_WITH: + { + parser_parse_with_statement_end (context_p); + continue; + } + + default: + { + break; + } + } + break; + } + } + + parser_stack_pop_uint8 (context_p); + context_p->last_statement.current_p = NULL; + + if (context_p->status_flags & PARSER_IS_CLOSURE) + { + parser_raise_error (context_p, PARSER_ERR_STATEMENT_EXPECTED); + } + +#if JERRY_LINE_INFO + if (context_p->line_info_p == NULL) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ +} /* parser_parse_statements */ + +/** + * Free jumps stored on the stack if a parse error is occurred. + */ +void JERRY_ATTR_NOINLINE +parser_free_jumps (parser_stack_iterator_t iterator) /**< iterator position */ +{ + while (true) + { + uint8_t type = parser_stack_iterator_read_uint8 (&iterator); + parser_branch_node_t *branch_list_p = NULL; + + switch (type) + { + case PARSER_STATEMENT_START: + { + return; + } + + case PARSER_STATEMENT_LABEL: + { + parser_label_statement_t label; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &label, sizeof (parser_label_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_label_statement_t)); + branch_list_p = label.break_list_p; + break; + } + + case PARSER_STATEMENT_SWITCH: + case PARSER_STATEMENT_SWITCH_NO_DEFAULT: + { + parser_switch_statement_t switch_statement; + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_loop_statement_t)); + parser_stack_iterator_read (&iterator, &switch_statement, sizeof (parser_switch_statement_t)); + parser_stack_iterator_skip (&iterator, sizeof (parser_switch_statement_t)); + + branch_list_p = switch_statement.branch_list_p; + while (branch_list_p != NULL) + { + parser_branch_node_t *next_p = branch_list_p->next_p; + parser_free (branch_list_p, sizeof (parser_branch_node_t)); + branch_list_p = next_p; + } + branch_list_p = loop.branch_list_p; + break; + } + + case PARSER_STATEMENT_DO_WHILE: + case PARSER_STATEMENT_WHILE: + case PARSER_STATEMENT_FOR: + case PARSER_STATEMENT_FOR_IN: + case PARSER_STATEMENT_FOR_OF: + { + parser_loop_statement_t loop; + + parser_stack_iterator_skip (&iterator, 1); + parser_stack_iterator_read (&iterator, &loop, sizeof (parser_loop_statement_t)); + parser_stack_iterator_skip (&iterator, parser_statement_length (type) - 1); + branch_list_p = loop.branch_list_p; + break; + } + + default: + { + parser_stack_iterator_skip (&iterator, parser_statement_length (type)); + continue; + } + } + + while (branch_list_p != NULL) + { + parser_branch_node_t *next_p = branch_list_p->next_p; + parser_free (branch_list_p, sizeof (parser_branch_node_t)); + branch_list_p = next_p; + } + } +} /* parser_free_jumps */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.cpp new file mode 100644 index 00000000..f2ce91ec --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.cpp @@ -0,0 +1,161 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-tagged-template-literal.h" + +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "js-lexer.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_tagged_template_literal Tagged template literal + * @{ + */ + +/** + * Append the cooked and raw string to the corresponding array + */ +void +parser_tagged_template_literal_append_strings (parser_context_t *context_p, /**< parser context */ + ecma_object_t *template_obj_p, /**< template object */ + ecma_object_t *raw_strings_p, /**< raw strings object */ + uint32_t prop_idx) /**< property index to set the values */ +{ + lexer_lit_location_t *lit_loc_p = &context_p->token.lit_location; + + if (lit_loc_p->length == 0 && !(lit_loc_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + ecma_builtin_helper_def_prop_by_index (template_obj_p, + prop_idx, + ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY), + ECMA_PROPERTY_FLAG_ENUMERABLE); + + ecma_builtin_helper_def_prop_by_index (raw_strings_p, + prop_idx, + ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY), + ECMA_PROPERTY_FLAG_ENUMERABLE); + return; + } + + uint8_t local_byte_array[LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE]; + const uint8_t *source_p = + lexer_convert_literal_to_chars (context_p, &context_p->token.lit_location, local_byte_array, LEXER_STRING_NO_OPTS); + + ecma_string_t *raw_str_p; + ecma_string_t *cooked_str_p = + ((lit_loc_p->status_flags & LEXER_FLAG_ASCII) ? ecma_new_ecma_string_from_ascii (source_p, lit_loc_p->length) + : ecma_new_ecma_string_from_utf8 (source_p, lit_loc_p->length)); + + parser_free_allocated_buffer (context_p); + + if (lit_loc_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + { + context_p->source_p = context_p->token.lit_location.char_p - 1; + lexer_parse_string (context_p, LEXER_STRING_RAW); + source_p = + lexer_convert_literal_to_chars (context_p, &context_p->token.lit_location, local_byte_array, LEXER_STRING_RAW); + + raw_str_p = + ((lit_loc_p->status_flags & LEXER_FLAG_ASCII) ? ecma_new_ecma_string_from_ascii (source_p, lit_loc_p->length) + : ecma_new_ecma_string_from_utf8 (source_p, lit_loc_p->length)); + + parser_free_allocated_buffer (context_p); + } + else + { + ecma_ref_ecma_string (cooked_str_p); + raw_str_p = cooked_str_p; + } + + ecma_builtin_helper_def_prop_by_index (template_obj_p, + prop_idx, + ecma_make_string_value (cooked_str_p), + ECMA_PROPERTY_FLAG_ENUMERABLE); + + ecma_builtin_helper_def_prop_by_index (raw_strings_p, + prop_idx, + ecma_make_string_value (raw_str_p), + ECMA_PROPERTY_FLAG_ENUMERABLE); + + ecma_deref_ecma_string (cooked_str_p); + ecma_deref_ecma_string (raw_str_p); +} /* parser_tagged_template_literal_append_strings */ + +/** + * Create new tagged template literal object + * + * @return pointer to the allocated object + */ +ecma_object_t * +parser_new_tagged_template_literal (ecma_object_t **raw_strings_p) /**< [out] raw strings object */ +{ + ecma_object_t *template_obj_p = ecma_op_new_array_object (0); + *raw_strings_p = ecma_op_new_array_object (0); + + ecma_extended_object_t *template_ext_obj_p = (ecma_extended_object_t *) template_obj_p; + ecma_extended_object_t *raw_ext_obj_p = (ecma_extended_object_t *) *raw_strings_p; + + const uint8_t flags = ECMA_PROPERTY_VIRTUAL | ECMA_PROPERTY_FLAG_WRITABLE | ECMA_FAST_ARRAY_FLAG; + JERRY_ASSERT (template_ext_obj_p->u.array.length_prop_and_hole_count == flags); + JERRY_ASSERT (raw_ext_obj_p->u.array.length_prop_and_hole_count == flags); + + template_ext_obj_p->u.array.length_prop_and_hole_count = flags | ECMA_ARRAY_TEMPLATE_LITERAL; + raw_ext_obj_p->u.array.length_prop_and_hole_count = flags | ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_builtin_helper_def_prop (template_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_RAW), + ecma_make_object_value (*raw_strings_p), + ECMA_PROPERTY_FIXED); + + return template_obj_p; +} /* parser_new_tagged_template_literal */ + +/** + * Set integrity level of the given template array object to "frozen" + */ +static void +parser_tagged_template_literal_freeze_array (ecma_object_t *obj_p /**< template object */) +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); + ecma_op_ordinary_object_prevent_extensions (obj_p); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; +} /* parser_tagged_template_literal_freeze_array */ + +/** + * Finalize the tagged template object + */ +void +parser_tagged_template_literal_finalize (ecma_object_t *template_obj_p, /**< template object */ + ecma_object_t *raw_strings_p) /**< raw strings object */ +{ + parser_tagged_template_literal_freeze_array (template_obj_p); + parser_tagged_template_literal_freeze_array (raw_strings_p); +} /* parser_tagged_template_literal_finalize */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.h new file mode 100644 index 00000000..919cc1b5 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-tagged-template-literal.h @@ -0,0 +1,49 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_TAGGED_TEMPLATE_LITERAL_H +#define ECMA_TAGGED_TEMPLATE_LITERAL_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_tagged_template_literal Tagged template literal + * @{ + */ + +#include "ecma-globals.h" + +#include "common.h" +#include "js-parser-internal.h" + +ecma_object_t *parser_new_tagged_template_literal (ecma_object_t **raw_strings_p); + +void parser_tagged_template_literal_append_strings (parser_context_t *context_p, + ecma_object_t *template_obj_p, + ecma_object_t *raw_strings_p, + uint32_t prop_index); + +void parser_tagged_template_literal_finalize (ecma_object_t *template_obj_p, ecma_object_t *raw_strings_p); + +/** + * @} + * @} + * @} + */ + +#endif /* ECMA_TAGGED_TEMPLATE_LITERAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-util.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-util.cpp new file mode 100644 index 00000000..c3ba131d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser-util.cpp @@ -0,0 +1,874 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers.h" + +#include "js-parser-internal.h" + +#if JERRY_PARSER + +#if JERRY_LINE_INFO +#include "jcontext.h" +#endif /* JERRY_LINE_INFO */ + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_utils Utility + * @{ + */ + +/**********************************************************************/ +/* Emitting byte codes */ +/**********************************************************************/ + +/** + * Append two bytes to the cbc stream. + */ +static void +parser_emit_two_bytes (parser_context_t *context_p, /**< context */ + uint8_t first_byte, /**< first byte */ + uint8_t second_byte) /**< second byte */ +{ + uint32_t last_position = context_p->byte_code.last_position; + + if (last_position + 2 <= PARSER_CBC_STREAM_PAGE_SIZE) + { + parser_mem_page_t *page_p = context_p->byte_code.last_p; + + page_p->bytes[last_position] = first_byte; + page_p->bytes[last_position + 1] = second_byte; + context_p->byte_code.last_position = last_position + 2; + } + else if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE) + { + parser_mem_page_t *page_p; + + parser_cbc_stream_alloc_page (context_p, &context_p->byte_code); + page_p = context_p->byte_code.last_p; + page_p->bytes[0] = first_byte; + page_p->bytes[1] = second_byte; + context_p->byte_code.last_position = 2; + } + else + { + context_p->byte_code.last_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] = first_byte; + parser_cbc_stream_alloc_page (context_p, &context_p->byte_code); + context_p->byte_code.last_p->bytes[0] = second_byte; + context_p->byte_code.last_position = 1; + } +} /* parser_emit_two_bytes */ + +/** + * Append byte to the end of the current byte code stream. + * + * @param context_p parser context + * @param byte byte + */ +#define PARSER_APPEND_TO_BYTE_CODE(context_p, byte) \ + if ((context_p)->byte_code.last_position >= PARSER_CBC_STREAM_PAGE_SIZE) \ + { \ + parser_cbc_stream_alloc_page ((context_p), &(context_p)->byte_code); \ + } \ + (context_p)->byte_code.last_p->bytes[(context_p)->byte_code.last_position++] = (uint8_t) (byte) + +#if JERRY_PARSER_DUMP_BYTE_CODE + +/** + * Print literal corresponding to the current index + */ +static void +parser_print_literal (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< index of literal */ +{ + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p; + parser_scope_stack_t *scope_stack_end_p = scope_stack_p + context_p->scope_stack_top; + bool in_scope_literal = false; + + while (scope_stack_p < scope_stack_end_p) + { + scope_stack_end_p--; + + if (scope_stack_end_p->map_from == PARSER_SCOPE_STACK_FUNC) + { + if (literal_index == scope_stack_end_p->map_to) + { + in_scope_literal = true; + break; + } + } + else if (literal_index == scanner_decode_map_to (scope_stack_end_p)) + { + in_scope_literal = true; + break; + } + } + + if (literal_index < PARSER_REGISTER_START) + { + JERRY_DEBUG_MSG (in_scope_literal ? " IDX:%d->" : " idx:%d->", literal_index); + lexer_literal_t *literal_p = PARSER_GET_LITERAL (literal_index); + util_print_literal (literal_p); + return; + } + + if (!in_scope_literal) + { + JERRY_DEBUG_MSG (" reg:%d", (int) (literal_index - PARSER_REGISTER_START)); + return; + } + + JERRY_DEBUG_MSG (" REG:%d->", (int) (literal_index - PARSER_REGISTER_START)); + + lexer_literal_t *literal_p = PARSER_GET_LITERAL (scope_stack_end_p->map_from); + util_print_literal (literal_p); +} /* parser_print_literal */ + +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + +/** + * Append the current byte code to the stream + */ +void +parser_flush_cbc (parser_context_t *context_p) /**< context */ +{ + uint8_t flags; + uint16_t last_opcode = context_p->last_cbc_opcode; + + if (last_opcode == PARSER_CBC_UNAVAILABLE) + { + return; + } + + context_p->status_flags |= PARSER_NO_END_LABEL; + + if (PARSER_IS_BASIC_OPCODE (last_opcode)) + { + cbc_opcode_t opcode = (cbc_opcode_t) last_opcode; + + JERRY_ASSERT (opcode < CBC_END); + flags = cbc_flags[opcode]; + + PARSER_APPEND_TO_BYTE_CODE (context_p, opcode); + context_p->byte_code_size++; + } + else + { + cbc_ext_opcode_t opcode = (cbc_ext_opcode_t) PARSER_GET_EXT_OPCODE (last_opcode); + + JERRY_ASSERT (opcode < CBC_EXT_END); + flags = cbc_ext_flags[opcode]; + parser_emit_two_bytes (context_p, CBC_EXT_OPCODE, (uint8_t) opcode); + context_p->byte_code_size += 2; + } + + JERRY_ASSERT ((flags >> CBC_STACK_ADJUST_SHIFT) >= CBC_STACK_ADJUST_BASE + || (CBC_STACK_ADJUST_BASE - (flags >> CBC_STACK_ADJUST_SHIFT)) <= context_p->stack_depth); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, CBC_STACK_ADJUST_VALUE (flags)); + + if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint16_t literal_index = context_p->last_cbc.literal_index; + + parser_emit_two_bytes (context_p, (uint8_t) (literal_index & 0xff), (uint8_t) (literal_index >> 8)); + context_p->byte_code_size += 2; + } + + if (flags & CBC_HAS_LITERAL_ARG2) + { + uint16_t literal_index = context_p->last_cbc.value; + + parser_emit_two_bytes (context_p, (uint8_t) (literal_index & 0xff), (uint8_t) (literal_index >> 8)); + context_p->byte_code_size += 2; + + if (!(flags & CBC_HAS_LITERAL_ARG)) + { + literal_index = context_p->last_cbc.third_literal_index; + + parser_emit_two_bytes (context_p, (uint8_t) (literal_index & 0xff), (uint8_t) (literal_index >> 8)); + context_p->byte_code_size += 2; + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + uint8_t byte_argument = (uint8_t) context_p->last_cbc.value; + + JERRY_ASSERT (context_p->last_cbc.value <= CBC_MAXIMUM_BYTE_VALUE); + + if (flags & CBC_POP_STACK_BYTE_ARG) + { + JERRY_ASSERT (context_p->stack_depth >= byte_argument); + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, byte_argument); + } + + PARSER_APPEND_TO_BYTE_CODE (context_p, byte_argument); + context_p->byte_code_size++; + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" [%3d] %s", + (int) context_p->stack_depth, + PARSER_IS_BASIC_OPCODE (last_opcode) ? cbc_names[last_opcode] + : cbc_ext_names[PARSER_GET_EXT_OPCODE (last_opcode)]); + + if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + parser_print_literal (context_p, context_p->last_cbc.literal_index); + } + + if (flags & CBC_HAS_LITERAL_ARG2) + { + parser_print_literal (context_p, context_p->last_cbc.value); + + if (!(flags & CBC_HAS_LITERAL_ARG)) + { + parser_print_literal (context_p, context_p->last_cbc.third_literal_index); + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + if (last_opcode == CBC_PUSH_NUMBER_POS_BYTE || last_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", (int) context_p->last_cbc.value + 1); + } + else if (last_opcode == CBC_PUSH_NUMBER_NEG_BYTE || last_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) + { + JERRY_DEBUG_MSG (" number:%d", -((int) context_p->last_cbc.value + 1)); + } + else + { + JERRY_DEBUG_MSG (" byte_arg:%d", (int) context_p->last_cbc.value); + } + } + + JERRY_DEBUG_MSG ("\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (context_p->stack_depth > context_p->stack_limit) + { + context_p->stack_limit = context_p->stack_depth; + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } + + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; +} /* parser_flush_cbc */ + +/** + * Append a byte code + */ +void +parser_emit_cbc (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, 0)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; +} /* parser_emit_cbc */ + +/** + * Append a byte code with a literal argument + */ +void +parser_emit_cbc_literal (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + uint16_t literal_index) /**< literal index */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_LITERAL_ARG)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.literal_index = literal_index; + context_p->last_cbc.literal_type = LEXER_UNUSED_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; +} /* parser_emit_cbc_literal */ + +/** + * Append a byte code with a literal and value argument + */ +void +parser_emit_cbc_literal_value (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + uint16_t literal_index, /**< literal index */ + uint16_t value) /**< value */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.literal_index = literal_index; + context_p->last_cbc.literal_type = LEXER_UNUSED_LITERAL; + context_p->last_cbc.literal_keyword_type = LEXER_EOS; + context_p->last_cbc.value = value; +} /* parser_emit_cbc_literal_value */ + +/** + * Append a byte code with the current literal argument + */ +void +parser_emit_cbc_literal_from_token (parser_context_t *context_p, /**< context */ + uint16_t opcode) /**< opcode */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_LITERAL_ARG)); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.literal_index = context_p->lit_object.index; + context_p->last_cbc.literal_type = context_p->token.lit_location.type; + context_p->last_cbc.literal_keyword_type = context_p->token.keyword_type; +} /* parser_emit_cbc_literal_from_token */ + +/** + * Append a byte code with a call argument + */ +void +parser_emit_cbc_call (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + size_t call_arguments) /**< number of arguments */ +{ + JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_BYTE_ARG)); + JERRY_ASSERT (call_arguments <= CBC_MAXIMUM_BYTE_VALUE); + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.value = (uint16_t) call_arguments; +} /* parser_emit_cbc_call */ + +/** + * Append a push number 1/2 byte code + */ +void +parser_emit_cbc_push_number (parser_context_t *context_p, /**< context */ + bool is_negative_number) /**< sign is negative */ +{ + uint16_t value = context_p->lit_object.index; + uint16_t lit_value = PARSER_INVALID_LITERAL_INDEX; + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + lit_value = context_p->last_cbc.literal_index; + } + else + { + if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_LITERAL; + lit_value = context_p->last_cbc.value; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + lit_value = context_p->last_cbc.third_literal_index; + } + + parser_flush_cbc (context_p); + } + } + + if (value == 0) + { + if (lit_value == PARSER_INVALID_LITERAL_INDEX) + { + context_p->last_cbc_opcode = CBC_PUSH_NUMBER_0; + return; + } + + context_p->last_cbc_opcode = CBC_PUSH_LITERAL_PUSH_NUMBER_0; + context_p->last_cbc.literal_index = lit_value; + return; + } + + uint16_t opcode; + + if (lit_value == PARSER_INVALID_LITERAL_INDEX) + { + opcode = (is_negative_number ? CBC_PUSH_NUMBER_NEG_BYTE : CBC_PUSH_NUMBER_POS_BYTE); + + JERRY_ASSERT (CBC_STACK_ADJUST_VALUE (PARSER_GET_FLAGS (opcode)) == 1); + } + else + { + opcode = (is_negative_number ? CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE : CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE); + JERRY_ASSERT (CBC_STACK_ADJUST_VALUE (PARSER_GET_FLAGS (opcode)) == 2); + + context_p->last_cbc.literal_index = lit_value; + } + + JERRY_ASSERT (value > 0 && value <= CBC_PUSH_NUMBER_BYTE_RANGE_END); + + context_p->last_cbc_opcode = opcode; + context_p->last_cbc.value = (uint16_t) (value - 1); +} /* parser_emit_cbc_push_number */ + +/** + * Append a byte code with a branch argument + */ +void +parser_emit_cbc_forward_branch (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + parser_branch_t *branch_p) /**< branch result */ +{ + uint8_t flags; + uint32_t extra_byte_code_increase; + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->status_flags |= PARSER_NO_END_LABEL; + + if (PARSER_IS_BASIC_OPCODE (opcode)) + { + JERRY_ASSERT (opcode < CBC_END); + flags = cbc_flags[opcode]; + extra_byte_code_increase = 0; + } + else + { + PARSER_APPEND_TO_BYTE_CODE (context_p, CBC_EXT_OPCODE); + opcode = (uint16_t) PARSER_GET_EXT_OPCODE (opcode); + + JERRY_ASSERT (opcode < CBC_EXT_END); + flags = cbc_ext_flags[opcode]; + extra_byte_code_increase = 1; + } + + JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG); + JERRY_ASSERT (CBC_BRANCH_IS_FORWARD (flags)); + JERRY_ASSERT (CBC_BRANCH_OFFSET_LENGTH (opcode) == 1); + + /* Branch opcodes never push anything onto the stack. */ + JERRY_ASSERT ((flags >> CBC_STACK_ADJUST_SHIFT) >= CBC_STACK_ADJUST_BASE + || (CBC_STACK_ADJUST_BASE - (flags >> CBC_STACK_ADJUST_SHIFT)) <= context_p->stack_depth); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, CBC_STACK_ADJUST_VALUE (flags)); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" [%3d] %s\n", + (int) context_p->stack_depth, + extra_byte_code_increase == 0 ? cbc_names[opcode] : cbc_ext_names[opcode]); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + PARSER_PLUS_EQUAL_U16 (opcode, PARSER_MAX_BRANCH_LENGTH - 1); + + parser_emit_two_bytes (context_p, (uint8_t) opcode, 0); + branch_p->page_p = context_p->byte_code.last_p; + branch_p->offset = (context_p->byte_code.last_position - 1) | (context_p->byte_code_size << 8); + + context_p->byte_code_size += extra_byte_code_increase; + +#if PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX + PARSER_APPEND_TO_BYTE_CODE (context_p, 0); +#else /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + parser_emit_two_bytes (context_p, 0, 0); +#endif /* PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX */ + + context_p->byte_code_size += PARSER_MAX_BRANCH_LENGTH + 1; + + if (context_p->stack_depth > context_p->stack_limit) + { + context_p->stack_limit = context_p->stack_depth; + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } +} /* parser_emit_cbc_forward_branch */ + +/** + * Append a branch byte code and create an item. + * + * @return newly created parser branch node + */ +parser_branch_node_t * +parser_emit_cbc_forward_branch_item (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + parser_branch_node_t *next_p) /**< next branch */ +{ + parser_branch_t branch; + parser_branch_node_t *new_item; + + /* Since byte code insertion may throw an out-of-memory error, + * the branch is constructed locally, and copied later. */ + parser_emit_cbc_forward_branch (context_p, opcode, &branch); + + new_item = (parser_branch_node_t *) parser_malloc (context_p, sizeof (parser_branch_node_t)); + new_item->branch = branch; + new_item->next_p = next_p; + return new_item; +} /* parser_emit_cbc_forward_branch_item */ + +/** + * Append a byte code with a branch argument + */ +void +parser_emit_cbc_backward_branch (parser_context_t *context_p, /**< context */ + uint16_t opcode, /**< opcode */ + uint32_t offset) /**< destination offset */ +{ + uint8_t flags; +#if JERRY_PARSER_DUMP_BYTE_CODE + const char *name; +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->status_flags |= PARSER_NO_END_LABEL; + offset = context_p->byte_code_size - offset; + + if (PARSER_IS_BASIC_OPCODE (opcode)) + { + JERRY_ASSERT (opcode < CBC_END); + flags = cbc_flags[opcode]; + +#if JERRY_PARSER_DUMP_BYTE_CODE + name = cbc_names[opcode]; +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + } + else + { + PARSER_APPEND_TO_BYTE_CODE (context_p, CBC_EXT_OPCODE); + opcode = (uint16_t) PARSER_GET_EXT_OPCODE (opcode); + + JERRY_ASSERT (opcode < CBC_EXT_END); + flags = cbc_ext_flags[opcode]; + context_p->byte_code_size++; + +#if JERRY_PARSER_DUMP_BYTE_CODE + name = cbc_ext_names[opcode]; +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + } + + JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG); + JERRY_ASSERT (CBC_BRANCH_IS_BACKWARD (flags)); + JERRY_ASSERT (CBC_BRANCH_OFFSET_LENGTH (opcode) == 1); + JERRY_ASSERT (offset <= context_p->byte_code_size); + + /* Branch opcodes never push anything onto the stack. */ + JERRY_ASSERT ((flags >> CBC_STACK_ADJUST_SHIFT) >= CBC_STACK_ADJUST_BASE + || (CBC_STACK_ADJUST_BASE - (flags >> CBC_STACK_ADJUST_SHIFT)) <= context_p->stack_depth); + PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, CBC_STACK_ADJUST_VALUE (flags)); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG (" [%3d] %s\n", (int) context_p->stack_depth, name); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + context_p->byte_code_size += 2; +#if PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX + if (offset > UINT16_MAX) + { + opcode++; + context_p->byte_code_size++; + } +#endif /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + + if (offset > UINT8_MAX) + { + opcode++; + context_p->byte_code_size++; + } + + PARSER_APPEND_TO_BYTE_CODE (context_p, (uint8_t) opcode); + +#if PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX + if (offset > UINT16_MAX) + { + PARSER_APPEND_TO_BYTE_CODE (context_p, offset >> 16); + } +#endif /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + + if (offset > UINT8_MAX) + { + PARSER_APPEND_TO_BYTE_CODE (context_p, (offset >> 8) & 0xff); + } + + PARSER_APPEND_TO_BYTE_CODE (context_p, offset & 0xff); +} /* parser_emit_cbc_backward_branch */ + +#undef PARSER_CHECK_LAST_POSITION +#undef PARSER_APPEND_TO_BYTE_CODE + +/** + * Helper function for parser. + * + * @return a new string based on encode. + */ +ecma_string_t * +parser_new_ecma_string_from_literal (lexer_literal_t *literal_p) /**< literal */ +{ + JERRY_ASSERT (literal_p != NULL); + + ecma_string_t *new_string = NULL; + + if (literal_p->status_flags & LEXER_FLAG_ASCII) + { + new_string = ecma_new_ecma_string_from_ascii (literal_p->u.char_p, literal_p->prop.length); + } + else + { + new_string = ecma_new_ecma_string_from_utf8 (literal_p->u.char_p, literal_p->prop.length); + } + + return new_string; +} /* parser_new_ecma_string_from_literal */ + +/** + * Set a branch to the current byte code position + */ +void +parser_set_branch_to_current_position (parser_context_t *context_p, /**< context */ + parser_branch_t *branch_p) /**< branch result */ +{ + uint32_t delta; + size_t offset; + parser_mem_page_t *page_p = branch_p->page_p; + + if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE) + { + parser_flush_cbc (context_p); + } + + context_p->status_flags &= (uint32_t) ~PARSER_NO_END_LABEL; + + JERRY_ASSERT (context_p->byte_code_size > (branch_p->offset >> 8)); + + delta = context_p->byte_code_size - (branch_p->offset >> 8); + offset = (branch_p->offset & CBC_LOWER_SEVEN_BIT_MASK); + + JERRY_ASSERT (delta <= PARSER_MAXIMUM_CODE_SIZE); + +#if PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX + page_p->bytes[offset++] = (uint8_t) (delta >> 8); + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + page_p = page_p->next_p; + offset = 0; + } +#else /* PARSER_MAXIMUM_CODE_SIZE > UINT16_MAX */ + page_p->bytes[offset++] = (uint8_t) (delta >> 16); + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + page_p = page_p->next_p; + offset = 0; + } + page_p->bytes[offset++] = (uint8_t) ((delta >> 8) & 0xff); + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + page_p = page_p->next_p; + offset = 0; + } +#endif /* PARSER_MAXIMUM_CODE_SIZE <= UINT16_MAX */ + page_p->bytes[offset] = delta & 0xff; +} /* parser_set_branch_to_current_position */ + +/** + * Set breaks to the current byte code position + */ +void +parser_set_breaks_to_current_position (parser_context_t *context_p, /**< context */ + parser_branch_node_t *current_p) /**< branch list */ +{ + while (current_p != NULL) + { + parser_branch_node_t *next_p = current_p->next_p; + + if (!(current_p->branch.offset & CBC_HIGHEST_BIT_MASK)) + { + parser_set_branch_to_current_position (context_p, ¤t_p->branch); + } + parser_free (current_p, sizeof (parser_branch_node_t)); + current_p = next_p; + } +} /* parser_set_breaks_to_current_position */ + +/** + * Set continues to the current byte code position + */ +void +parser_set_continues_to_current_position (parser_context_t *context_p, /**< context */ + parser_branch_node_t *current_p) /**< branch list */ +{ + while (current_p != NULL) + { + if (current_p->branch.offset & CBC_HIGHEST_BIT_MASK) + { + parser_set_branch_to_current_position (context_p, ¤t_p->branch); + } + current_p = current_p->next_p; + } +} /* parser_set_continues_to_current_position */ + +/** + * Return the size of internal record corresponding to a class field + * + * @return internal record size + */ +static size_t +parser_get_class_field_info_size (uint8_t class_field_type) /**< class field type */ +{ + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + return sizeof (scanner_range_t) + 1; + } + + if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + return sizeof (scanner_location_t) + 1; + } + + return 1; +} /* parser_get_class_field_info_size */ + +/** + * Reverse the field list of a class + */ +void +parser_reverse_class_fields (parser_context_t *context_p, /**< context */ + size_t fields_size) /**< size of consumed memory */ +{ + uint8_t *data_p = (uint8_t *) parser_malloc (context_p, fields_size); + uint8_t *data_end_p = data_p + fields_size; + uint8_t *current_p = data_p; + bool has_fields = false; + parser_stack_iterator_t iterator; + + JERRY_ASSERT (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_END)); + + parser_stack_iterator_init (context_p, &iterator); + + do + { + uint8_t class_field_type = parser_stack_iterator_read_uint8 (&iterator); + size_t info_size = parser_get_class_field_info_size (class_field_type); + + parser_stack_iterator_read (&iterator, current_p, info_size); + parser_stack_iterator_skip (&iterator, info_size); + current_p += info_size; + + if (!(class_field_type & PARSER_CLASS_FIELD_STATIC)) + { + has_fields = true; + context_p->stack_top_uint8 = class_field_type; + } + } while (current_p < data_end_p); + + parser_stack_iterator_init (context_p, &iterator); + current_p = data_end_p; + + bool has_static_fields = false; + + if (has_fields) + { + do + { + uint8_t class_field_type = current_p[-1]; + + size_t info_size = parser_get_class_field_info_size (class_field_type); + + if (!(class_field_type & PARSER_CLASS_FIELD_STATIC)) + { + current_p -= info_size; + parser_stack_iterator_write (&iterator, current_p, info_size); + parser_stack_iterator_skip (&iterator, info_size); + continue; + } + + if (!has_static_fields) + { + has_static_fields = true; + current_p[-1] |= PARSER_CLASS_FIELD_END; + } + current_p -= info_size; + } while (current_p > data_p); + } + else + { + /* All class fields are static. */ + has_static_fields = true; + JERRY_ASSERT (data_end_p[-1] & PARSER_CLASS_FIELD_STATIC); + context_p->stack_top_uint8 = data_end_p[-1]; + } + + if (has_static_fields) + { + current_p = data_end_p; + + do + { + uint8_t class_field_type = current_p[-1]; + + size_t info_size = parser_get_class_field_info_size (class_field_type); + current_p -= info_size; + + if (class_field_type & PARSER_CLASS_FIELD_STATIC) + { + parser_stack_iterator_write (&iterator, current_p, info_size); + parser_stack_iterator_skip (&iterator, info_size); + } + } while (current_p > data_p); + } + + parser_free (data_p, fields_size); +} /* parser_reverse_class_fields */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.cpp new file mode 100644 index 00000000..f7559bb3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.cpp @@ -0,0 +1,3218 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-exceptions.h" +#include "ecma-extended-info.h" +#include "ecma-helpers.h" +#include "ecma-literal-storage.h" +#include "ecma-module.h" + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "lit-char-helpers.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_parser Parser + * @{ + */ + +#if JERRY_PARSER + +JERRY_STATIC_ASSERT (((int) ECMA_PARSE_STRICT_MODE == (int) PARSER_IS_STRICT), + ecma_parse_strict_mode_must_be_equal_to_parser_is_strict); + +JERRY_STATIC_ASSERT (PARSER_SAVE_STATUS_FLAGS (PARSER_ALLOW_SUPER) == 0x1, incorrect_saving_of_ecma_parse_allow_super); +JERRY_STATIC_ASSERT ((PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_ALLOW_SUPER) == PARSER_ALLOW_SUPER), + incorrect_restoring_of_ecma_parse_allow_super); + +JERRY_STATIC_ASSERT ((PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_FUNCTION_CONTEXT) == 0), + ecma_parse_function_context_must_not_be_transformed); + +/** + * Compute real literal indicies. + * + * @return length of the prefix opcodes + */ +static void +parser_compute_indicies (parser_context_t *context_p, /**< context */ + uint16_t *ident_end, /**< end of the identifier group */ + uint16_t *const_literal_end) /**< end of the const literal group */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + + uint16_t ident_count = 0; + uint16_t const_literal_count = 0; + + uint16_t ident_index; + uint16_t const_literal_index; + uint16_t literal_index; + + /* First phase: count the number of items in each group. */ + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + if (literal_p->status_flags & LEXER_FLAG_USED) + { + ident_count++; + break; + } + else if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) + { + jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length); + /* This literal should not be freed even if an error is encountered later. */ + literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR; + } + continue; + } + case LEXER_STRING_LITERAL: + { + const_literal_count++; + break; + } + case LEXER_NUMBER_LITERAL: + { + const_literal_count++; + continue; + } + case LEXER_FUNCTION_LITERAL: + case LEXER_REGEXP_LITERAL: + { + continue; + } + default: + { + JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL); + continue; + } + } + + const uint8_t *char_p = literal_p->u.char_p; + uint32_t status_flags = context_p->status_flags; + + if ((literal_p->status_flags & LEXER_FLAG_SOURCE_PTR) && literal_p->prop.length < 0xfff) + { + size_t bytes_to_end = (size_t) (context_p->source_end_p - char_p); + + if (bytes_to_end < 0xfffff) + { + literal_p->u.source_data = ((uint32_t) bytes_to_end) | (((uint32_t) literal_p->prop.length) << 20); + literal_p->status_flags |= LEXER_FLAG_LATE_INIT; + status_flags |= PARSER_HAS_LATE_LIT_INIT; + context_p->status_flags = status_flags; + char_p = NULL; + } + } + + if (char_p != NULL) + { + literal_p->u.value = ecma_find_or_create_literal_string (char_p, + literal_p->prop.length, + (literal_p->status_flags & LEXER_FLAG_ASCII) != 0); + + if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) + { + jmem_heap_free_block ((void *) char_p, literal_p->prop.length); + /* This literal should not be freed even if an error is encountered later. */ + literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR; + } + } + } + + ident_index = context_p->register_count; + const_literal_index = (uint16_t) (ident_index + ident_count); + literal_index = (uint16_t) (const_literal_index + const_literal_count); + + /* Second phase: Assign an index to each literal. */ + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + if (literal_p->status_flags & LEXER_FLAG_USED) + { + literal_p->prop.index = ident_index; + ident_index++; + } + break; + } + case LEXER_STRING_LITERAL: + case LEXER_NUMBER_LITERAL: + { + JERRY_ASSERT ((literal_p->status_flags & ~(LEXER_FLAG_SOURCE_PTR | LEXER_FLAG_LATE_INIT)) == 0); + literal_p->prop.index = const_literal_index; + const_literal_index++; + break; + } + case LEXER_FUNCTION_LITERAL: + case LEXER_REGEXP_LITERAL: + { + JERRY_ASSERT (literal_p->status_flags == 0); + + literal_p->prop.index = literal_index; + literal_index++; + break; + } + default: + { + JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL + && literal_p->status_flags == LEXER_FLAG_FUNCTION_ARGUMENT); + break; + } + } + } + + JERRY_ASSERT (ident_index == context_p->register_count + ident_count); + JERRY_ASSERT (const_literal_index == ident_index + const_literal_count); + JERRY_ASSERT (literal_index <= context_p->register_count + context_p->literal_count); + + context_p->literal_count = literal_index; + + *ident_end = ident_index; + *const_literal_end = const_literal_index; +} /* parser_compute_indicies */ + +/** + * Initialize literal pool. + */ +static void +parser_init_literal_pool (parser_context_t *context_p, /**< context */ + ecma_value_t *literal_pool_p) /**< start of literal pool */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + switch (literal_p->type) + { + case LEXER_IDENT_LITERAL: + { + if (!(literal_p->status_flags & LEXER_FLAG_USED)) + { + break; + } + /* FALLTHRU */ + } + case LEXER_STRING_LITERAL: + { + ecma_value_t lit_value = literal_p->u.value; + + JERRY_ASSERT (literal_p->prop.index >= context_p->register_count); + literal_pool_p[literal_p->prop.index] = lit_value; + break; + } + case LEXER_NUMBER_LITERAL: + { + JERRY_ASSERT (literal_p->prop.index >= context_p->register_count); + + literal_pool_p[literal_p->prop.index] = literal_p->u.value; + break; + } + case LEXER_FUNCTION_LITERAL: + case LEXER_REGEXP_LITERAL: + { + JERRY_ASSERT (literal_p->prop.index >= context_p->register_count); + + ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[literal_p->prop.index], literal_p->u.bytecode_p); + break; + } + default: + { + JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL); + break; + } + } + } +} /* parser_init_literal_pool */ + +/* + * During byte code post processing certain bytes are not + * copied into the final byte code buffer. For example, if + * one byte is enough for encoding a literal index, the + * second byte is not copied. However, when a byte is skipped, + * the offsets of those branches which crosses (jumps over) + * that byte code should also be decreased by one. Instead + * of finding these jumps every time when a byte is skipped, + * all branch offset updates are computed in one step. + * + * Branch offset mapping example: + * + * Let's assume that each parser_mem_page of the byte_code + * buffer is 8 bytes long and only 4 bytes are kept for a + * given page: + * + * +---+---+---+---+---+---+---+---+ + * | X | 1 | 2 | 3 | X | 4 | X | X | + * +---+---+---+---+---+---+---+---+ + * + * X marks those bytes which are removed. The resulting + * offset mapping is the following: + * + * +---+---+---+---+---+---+---+---+ + * | 0 | 1 | 2 | 3 | 3 | 4 | 4 | 4 | + * +---+---+---+---+---+---+---+---+ + * + * Each X is simply replaced by the index of the previous + * index starting from zero. This shows the number of + * copied bytes before a given byte including the byte + * itself. The last byte always shows the number of bytes + * copied from this page. + * + * This mapping allows recomputing all branch targets, + * since mapping[to] - mapping[from] is the new argument + * for forward branches. As for backward branches, the + * equation is reversed to mapping[from] - mapping[to]. + * + * The mapping is relative to one page, so distance + * computation affecting multiple pages requires a loop. + * We should also note that only argument bytes can + * be skipped, so removed bytes cannot be targeted by + * branches. Valid branches always target instruction + * starts only. + */ + +/** + * Recompute the argument of a forward branch. + * + * @return the new distance + */ +static size_t +parser_update_forward_branch (parser_mem_page_t *page_p, /**< current page */ + size_t full_distance, /**< full distance */ + uint8_t bytes_copied_before_jump) /**< bytes copied before jump */ +{ + size_t new_distance = 0; + + while (full_distance > PARSER_CBC_STREAM_PAGE_SIZE) + { + new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + full_distance -= PARSER_CBC_STREAM_PAGE_SIZE; + page_p = page_p->next_p; + } + + new_distance += page_p->bytes[full_distance - 1] & CBC_LOWER_SEVEN_BIT_MASK; + return new_distance - bytes_copied_before_jump; +} /* parser_update_forward_branch */ + +/** + * Recompute the argument of a backward branch. + * + * @return the new distance + */ +static size_t +parser_update_backward_branch (parser_mem_page_t *page_p, /**< current page */ + size_t full_distance, /**< full distance */ + uint8_t bytes_copied_before_jump) /**< bytes copied before jump */ +{ + size_t new_distance = bytes_copied_before_jump; + + while (full_distance >= PARSER_CBC_STREAM_PAGE_SIZE) + { + JERRY_ASSERT (page_p != NULL); + new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + full_distance -= PARSER_CBC_STREAM_PAGE_SIZE; + page_p = page_p->next_p; + } + + if (full_distance > 0) + { + size_t offset = PARSER_CBC_STREAM_PAGE_SIZE - full_distance; + + JERRY_ASSERT (page_p != NULL); + + new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + new_distance -= page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK; + } + + return new_distance; +} /* parser_update_backward_branch */ + +/** + * Update targets of all branches in one step. + */ +static void +parse_update_branches (parser_context_t *context_p, /**< context */ + uint8_t *byte_code_p) /**< byte code */ +{ + parser_mem_page_t *page_p = context_p->byte_code.first_p; + parser_mem_page_t *prev_page_p = NULL; + parser_mem_page_t *last_page_p = context_p->byte_code.last_p; + size_t last_position = context_p->byte_code.last_position; + size_t offset = 0; + size_t bytes_copied = 0; + + if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE) + { + last_page_p = NULL; + last_position = 0; + } + + while (page_p != last_page_p || offset < last_position) + { + /* Branch instructions are marked to improve search speed. */ + if (page_p->bytes[offset] & CBC_HIGHEST_BIT_MASK) + { + uint8_t *bytes_p = byte_code_p + bytes_copied; + uint8_t flags; + uint8_t bytes_copied_before_jump = 0; + size_t branch_argument_length; + size_t target_distance; + size_t length; + + if (offset > 0) + { + bytes_copied_before_jump = page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK; + } + bytes_p += bytes_copied_before_jump; + + if (*bytes_p == CBC_EXT_OPCODE) + { + bytes_p++; + flags = cbc_ext_flags[*bytes_p]; + } + else + { + flags = cbc_flags[*bytes_p]; + } + + JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG); + branch_argument_length = CBC_BRANCH_OFFSET_LENGTH (*bytes_p); + bytes_p++; + + /* Decoding target. */ + length = branch_argument_length; + target_distance = 0; + do + { + target_distance = (target_distance << 8) | *bytes_p; + bytes_p++; + } while (--length > 0); + + if (CBC_BRANCH_IS_FORWARD (flags)) + { + /* Branch target was not set. */ + JERRY_ASSERT (target_distance > 0); + + target_distance = parser_update_forward_branch (page_p, offset + target_distance, bytes_copied_before_jump); + } + else + { + if (target_distance < offset) + { + uint8_t bytes_copied_before_target = page_p->bytes[offset - target_distance - 1]; + bytes_copied_before_target = bytes_copied_before_target & CBC_LOWER_SEVEN_BIT_MASK; + + target_distance = (size_t) (bytes_copied_before_jump - bytes_copied_before_target); + } + else if (target_distance == offset) + { + target_distance = bytes_copied_before_jump; + } + else + { + target_distance = + parser_update_backward_branch (prev_page_p, target_distance - offset, bytes_copied_before_jump); + } + } + + /* Encoding target again. */ + do + { + bytes_p--; + *bytes_p = (uint8_t) (target_distance & 0xff); + target_distance >>= 8; + } while (--branch_argument_length > 0); + } + + offset++; + if (offset >= PARSER_CBC_STREAM_PAGE_SIZE) + { + parser_mem_page_t *next_p = page_p->next_p; + + /* We reverse the pages before the current page. */ + page_p->next_p = prev_page_p; + prev_page_p = page_p; + + bytes_copied += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK; + page_p = next_p; + offset = 0; + } + } + + /* After this point the pages of the byte code stream are + * not used anymore. However, they needs to be freed during + * cleanup, so the first and last pointers of the stream + * descriptor are reversed as well. */ + if (last_page_p != NULL) + { + JERRY_ASSERT (last_page_p == context_p->byte_code.last_p); + last_page_p->next_p = prev_page_p; + } + else + { + last_page_p = context_p->byte_code.last_p; + } + + context_p->byte_code.last_p = context_p->byte_code.first_p; + context_p->byte_code.first_p = last_page_p; +} /* parse_update_branches */ + +/** + * Forward iterator: move to the next byte code + * + * @param page_p page + * @param offset offset + */ +#define PARSER_NEXT_BYTE(page_p, offset) \ + do \ + { \ + if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \ + { \ + offset = 0; \ + page_p = page_p->next_p; \ + } \ + } while (0) + +/** + * Forward iterator: move to the next byte code. Also updates the offset of the previous byte code. + * + * @param page_p page + * @param offset offset + * @param real_offset real offset + */ +#define PARSER_NEXT_BYTE_UPDATE(page_p, offset, real_offset) \ + do \ + { \ + page_p->bytes[offset] = real_offset; \ + if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \ + { \ + offset = 0; \ + real_offset = 0; \ + page_p = page_p->next_p; \ + } \ + } while (0) + +/** + * Post processing main function. + * + * @return compiled code + */ +static ecma_compiled_code_t * +parser_post_processing (parser_context_t *context_p) /**< context */ +{ + uint16_t literal_one_byte_limit; + uint16_t ident_end; + uint16_t const_literal_end; + parser_mem_page_t *page_p; + parser_mem_page_t *last_page_p; + size_t last_position; + size_t offset; + size_t length; + size_t literal_length; + size_t total_size; + uint8_t real_offset; + uint8_t *byte_code_p; + bool needs_uint16_arguments; + cbc_opcode_t last_opcode = CBC_EXT_OPCODE; + ecma_compiled_code_t *compiled_code_p; + ecma_value_t *literal_pool_p; + uint8_t *dst_p; + + if ((context_p->status_flags & (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED)) + == (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED)) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED; + + parser_emit_cbc (context_p, CBC_CONTEXT_END); + + parser_branch_t branch; + parser_stack_pop (context_p, &branch, sizeof (parser_branch_t)); + parser_set_branch_to_current_position (context_p, &branch); + + JERRY_ASSERT (!(context_p->status_flags & PARSER_NO_END_LABEL)); + } + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#ifndef JERRY_NDEBUG + PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + + if (context_p->stack_limit < PARSER_FINALLY_CONTEXT_STACK_ALLOCATION) + { + context_p->stack_limit = PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + } + + parser_branch_t branch; + + parser_stack_pop (context_p, &branch, sizeof (parser_branch_t)); + parser_set_branch_to_current_position (context_p, &branch); + + JERRY_ASSERT (!(context_p->status_flags & PARSER_NO_END_LABEL)); + } + +#if JERRY_LINE_INFO + JERRY_ASSERT (context_p->line_info_p != NULL); +#endif /* JERRY_LINE_INFO */ + + JERRY_ASSERT (context_p->stack_depth == 0); +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context_p->context_stack_depth == 0); +#endif /* !JERRY_NDEBUG */ + + if ((size_t) context_p->stack_limit + (size_t) context_p->register_count > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + + if (JERRY_UNLIKELY (context_p->script_p->refs_and_type >= CBC_SCRIPT_REF_MAX)) + { + /* This is probably never happens in practice. */ + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } + + context_p->script_p->refs_and_type += CBC_SCRIPT_REF_ONE; + + JERRY_ASSERT (context_p->literal_count <= PARSER_MAXIMUM_NUMBER_OF_LITERALS); + + parser_compute_indicies (context_p, &ident_end, &const_literal_end); + + if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE) + { + literal_one_byte_limit = CBC_MAXIMUM_BYTE_VALUE - 1; + } + else + { + literal_one_byte_limit = CBC_LOWER_SEVEN_BIT_MASK; + } + + last_page_p = context_p->byte_code.last_p; + last_position = context_p->byte_code.last_position; + + if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE) + { + last_page_p = NULL; + last_position = 0; + } + + page_p = context_p->byte_code.first_p; + offset = 0; + length = 0; + + while (page_p != last_page_p || offset < last_position) + { + uint8_t *opcode_p; + uint8_t flags; + size_t branch_offset_length; + + opcode_p = page_p->bytes + offset; + last_opcode = (cbc_opcode_t) (*opcode_p); + PARSER_NEXT_BYTE (page_p, offset); + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (last_opcode); + flags = cbc_flags[last_opcode]; + length++; + + switch (last_opcode) + { + case CBC_EXT_OPCODE: + { + cbc_ext_opcode_t ext_opcode; + + ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset]; + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode); + flags = cbc_ext_flags[ext_opcode]; + PARSER_NEXT_BYTE (page_p, offset); + length++; + break; + } + case CBC_POST_DECR: + { + *opcode_p = CBC_PRE_DECR; + break; + } + case CBC_POST_INCR: + { + *opcode_p = CBC_PRE_INCR; + break; + } + case CBC_POST_DECR_IDENT: + { + *opcode_p = CBC_PRE_DECR_IDENT; + break; + } + case CBC_POST_INCR_IDENT: + { + *opcode_p = CBC_PRE_INCR_IDENT; + break; + } + default: + { + break; + } + } + + while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint8_t *first_byte = page_p->bytes + offset; + uint32_t literal_index = *first_byte; + + PARSER_NEXT_BYTE (page_p, offset); + length++; + + literal_index |= ((uint32_t) page_p->bytes[offset]) << 8; + + if (literal_index >= PARSER_REGISTER_START) + { + literal_index -= PARSER_REGISTER_START; + } + else + { + literal_index = (PARSER_GET_LITERAL (literal_index))->prop.index; + } + + if (literal_index <= literal_one_byte_limit) + { + *first_byte = (uint8_t) literal_index; + } + else + { + if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE) + { + JERRY_ASSERT (literal_index <= CBC_MAXIMUM_SMALL_VALUE); + *first_byte = CBC_MAXIMUM_BYTE_VALUE; + page_p->bytes[offset] = (uint8_t) (literal_index - CBC_MAXIMUM_BYTE_VALUE); + length++; + } + else + { + JERRY_ASSERT (literal_index <= CBC_MAXIMUM_FULL_VALUE); + *first_byte = (uint8_t) ((literal_index >> 8) | CBC_HIGHEST_BIT_MASK); + page_p->bytes[offset] = (uint8_t) (literal_index & 0xff); + length++; + } + } + PARSER_NEXT_BYTE (page_p, offset); + + if (flags & CBC_HAS_LITERAL_ARG2) + { + if (flags & CBC_HAS_LITERAL_ARG) + { + flags = CBC_HAS_LITERAL_ARG; + } + else + { + flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2; + } + } + else + { + break; + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + /* This argument will be copied without modification. */ + PARSER_NEXT_BYTE (page_p, offset); + length++; + } + + if (flags & CBC_HAS_BRANCH_ARG) + { + bool prefix_zero = true; + + /* The leading zeroes are dropped from the stream. + * Although dropping these zeroes for backward + * branches are unnecessary, we use the same + * code path for simplicity. */ + JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3); + + while (--branch_offset_length > 0) + { + uint8_t byte = page_p->bytes[offset]; + if (byte > 0 || !prefix_zero) + { + prefix_zero = false; + length++; + } + else + { + JERRY_ASSERT (CBC_BRANCH_IS_FORWARD (flags)); + } + PARSER_NEXT_BYTE (page_p, offset); + } + + if (last_opcode == (cbc_opcode_t) (CBC_JUMP_FORWARD + PARSER_MAX_BRANCH_LENGTH - 1) && prefix_zero + && page_p->bytes[offset] == PARSER_MAX_BRANCH_LENGTH + 1) + { + /* Uncoditional jumps which jump right after the instruction + * are effectively NOPs. These jumps are removed from the + * stream. The 1 byte long CBC_JUMP_FORWARD form marks these + * instructions, since this form is constructed during post + * processing and cannot be emitted directly. */ + *opcode_p = CBC_JUMP_FORWARD; + length--; + } + else + { + /* Other last bytes are always copied. */ + length++; + } + + PARSER_NEXT_BYTE (page_p, offset); + } + } + + if (!(context_p->status_flags & PARSER_NO_END_LABEL) || !(PARSER_OPCODE_IS_RETURN (last_opcode))) + { + context_p->status_flags &= (uint32_t) ~PARSER_NO_END_LABEL; + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + length++; + } + + length++; + } + + needs_uint16_arguments = false; + total_size = sizeof (cbc_uint8_arguments_t); + + if (context_p->stack_limit > CBC_MAXIMUM_BYTE_VALUE || context_p->register_count > CBC_MAXIMUM_BYTE_VALUE + || context_p->literal_count > CBC_MAXIMUM_BYTE_VALUE) + { + needs_uint16_arguments = true; + total_size = sizeof (cbc_uint16_arguments_t); + } + + literal_length = (size_t) (context_p->literal_count - context_p->register_count) * sizeof (ecma_value_t); + + total_size += literal_length + length; + + if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) + { + total_size += context_p->argument_count * sizeof (ecma_value_t); + } + + /* function.name */ + if (!(context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)) + { + total_size += sizeof (ecma_value_t); + } + + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + total_size += sizeof (ecma_value_t); + } + +#if JERRY_LINE_INFO + total_size += sizeof (ecma_value_t); +#endif /* JERRY_LINE_INFO */ + uint8_t extended_info = 0; + + if (context_p->argument_length != UINT16_MAX) + { + extended_info |= CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH; + total_size += ecma_extended_info_get_encoded_length (context_p->argument_length); + } +#if JERRY_FUNCTION_TO_STRING + if (context_p->last_context_p != NULL) + { + extended_info |= CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE; + + const uint8_t *start_p = context_p->source_start_p; + const uint8_t *function_start_p = context_p->last_context_p->function_start_p; + + if (function_start_p < start_p || function_start_p >= start_p + context_p->source_size) + { + JERRY_ASSERT (context_p->arguments_start_p != NULL && function_start_p >= context_p->arguments_start_p + && function_start_p < context_p->arguments_start_p + context_p->arguments_size); + + start_p = context_p->arguments_start_p; + extended_info |= CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS; + } + + total_size += ecma_extended_info_get_encoded_length ((uint32_t) (function_start_p - start_p)); + total_size += ecma_extended_info_get_encoded_length ((uint32_t) (context_p->function_end_p - function_start_p)); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + if (extended_info != 0) + { + total_size += sizeof (uint8_t); + } + + total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT); + compiled_code_p = (ecma_compiled_code_t *) parser_malloc (context_p, total_size); + +#if JERRY_SNAPSHOT_SAVE || JERRY_PARSER_DUMP_BYTE_CODE + // Avoid getting junk bytes + memset (compiled_code_p, 0, total_size); +#endif /* JERRY_SNAPSHOT_SAVE || JERRY_PARSER_DUMP_BYTE_CODE */ + + byte_code_p = (uint8_t *) compiled_code_p; + compiled_code_p->size = (uint16_t) (total_size >> JMEM_ALIGNMENT_LOG); + compiled_code_p->refs = 1; + compiled_code_p->status_flags = 0; + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + JERRY_ASSERT (context_p->argument_count > 0); + context_p->argument_count--; + } + + if (needs_uint16_arguments) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + + args_p->stack_limit = context_p->stack_limit; + args_p->script_value = context_p->script_value; + args_p->argument_end = context_p->argument_count; + args_p->register_end = context_p->register_count; + args_p->ident_end = ident_end; + args_p->const_literal_end = const_literal_end; + args_p->literal_end = context_p->literal_count; + + compiled_code_p->status_flags |= CBC_CODE_FLAGS_UINT16_ARGUMENTS; + byte_code_p += sizeof (cbc_uint16_arguments_t); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + + args_p->stack_limit = (uint8_t) context_p->stack_limit; + args_p->argument_end = (uint8_t) context_p->argument_count; + args_p->script_value = context_p->script_value; + args_p->register_end = (uint8_t) context_p->register_count; + args_p->ident_end = (uint8_t) ident_end; + args_p->const_literal_end = (uint8_t) const_literal_end; + args_p->literal_end = (uint8_t) context_p->literal_count; + + byte_code_p += sizeof (cbc_uint8_arguments_t); + } + + uint16_t encoding_limit; + uint16_t encoding_delta; + + if (context_p->literal_count > CBC_MAXIMUM_SMALL_VALUE) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_FULL_LITERAL_ENCODING; + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + + if (context_p->status_flags & PARSER_IS_STRICT) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_STRICT_MODE; + } + + if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED) && PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED; + } + + if (!(context_p->status_flags & PARSER_LEXICAL_ENV_NEEDED)) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED; + } + + uint16_t function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_NORMAL); + + if (context_p->status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER)) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ACCESSOR); + } + else if (!(context_p->status_flags & PARSER_IS_FUNCTION)) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_SCRIPT); + } + else if (context_p->status_flags & PARSER_IS_ARROW_FUNCTION) + { + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ASYNC_ARROW); + } + else + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ARROW); + } + } + else if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ASYNC_GENERATOR); + } + else + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_GENERATOR); + } + } + else if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ASYNC); + } + else if (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_CONSTRUCTOR); + } + else if (context_p->status_flags & PARSER_IS_METHOD) + { + function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_METHOD); + } + + if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + { + JERRY_ASSERT (!(context_p->status_flags & PARSER_IS_FUNCTION)); + compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED; + } + + compiled_code_p->status_flags |= function_type; + +#if JERRY_LINE_INFO + compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_LINE_INFO; +#endif /* JERRY_LINE_INFO */ + + literal_pool_p = ((ecma_value_t *) byte_code_p) - context_p->register_count; + byte_code_p += literal_length; + dst_p = byte_code_p; + + parser_init_literal_pool (context_p, literal_pool_p); + + page_p = context_p->byte_code.first_p; + offset = 0; + real_offset = 0; + uint8_t last_register_index = + (uint8_t) JERRY_MIN (context_p->register_count, (PARSER_MAXIMUM_NUMBER_OF_REGISTERS - 1)); + + while (page_p != last_page_p || offset < last_position) + { + uint8_t flags; + uint8_t *opcode_p; + uint8_t *branch_mark_p; + cbc_opcode_t opcode; + size_t branch_offset_length; + + opcode_p = dst_p; + branch_mark_p = page_p->bytes + offset; + opcode = (cbc_opcode_t) (*branch_mark_p); + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode); + + if (opcode == CBC_JUMP_FORWARD) + { + /* These opcodes are deleted from the stream. */ + size_t counter = PARSER_MAX_BRANCH_LENGTH + 1; + + do + { + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + } while (--counter > 0); + + continue; + } + + /* Storing the opcode */ + *dst_p++ = (uint8_t) opcode; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + flags = cbc_flags[opcode]; + + if (opcode == CBC_EXT_OPCODE) + { + cbc_ext_opcode_t ext_opcode; + + ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset]; + flags = cbc_ext_flags[ext_opcode]; + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode); + + /* Storing the extended opcode */ + *dst_p++ = (uint8_t) ext_opcode; + opcode_p++; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + } + + /* Only literal and call arguments can be combined. */ + JERRY_ASSERT (!(flags & CBC_HAS_BRANCH_ARG) || !(flags & (CBC_HAS_BYTE_ARG | CBC_HAS_LITERAL_ARG))); + + while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)) + { + uint16_t first_byte = page_p->bytes[offset]; + + uint8_t *opcode_pos_p = dst_p - 1; + *dst_p++ = (uint8_t) first_byte; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + + if (first_byte > literal_one_byte_limit) + { + *dst_p++ = page_p->bytes[offset]; + + if (first_byte >= encoding_limit) + { + first_byte = (uint16_t) (((first_byte << 8) | dst_p[-1]) - encoding_delta); + } + real_offset++; + } + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + + if (flags & CBC_HAS_LITERAL_ARG2) + { + if (flags & CBC_HAS_LITERAL_ARG) + { + flags = CBC_HAS_LITERAL_ARG; + } + else + { + flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2; + } + } + else + { + if (opcode == CBC_ASSIGN_SET_IDENT && JERRY_LIKELY (first_byte < last_register_index)) + { + *opcode_pos_p = CBC_MOV_IDENT; + } + + break; + } + } + + if (flags & CBC_HAS_BYTE_ARG) + { + /* This argument will be copied without modification. */ + *dst_p++ = page_p->bytes[offset]; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + continue; + } + + if (flags & CBC_HAS_BRANCH_ARG) + { + *branch_mark_p |= CBC_HIGHEST_BIT_MASK; + bool prefix_zero = true; + + /* The leading zeroes are dropped from the stream. */ + JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3); + + while (--branch_offset_length > 0) + { + uint8_t byte = page_p->bytes[offset]; + if (byte > 0 || !prefix_zero) + { + prefix_zero = false; + *dst_p++ = page_p->bytes[offset]; + real_offset++; + } + else + { + /* When a leading zero is dropped, the branch + * offset length must be decreased as well. */ + (*opcode_p)--; + } + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + } + + *dst_p++ = page_p->bytes[offset]; + real_offset++; + PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset); + continue; + } + } + + if (!(context_p->status_flags & PARSER_NO_END_LABEL)) + { + *dst_p++ = CBC_RETURN_FUNCTION_END; + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + dst_p[-1] = CBC_EXT_OPCODE; + dst_p[0] = CBC_EXT_ASYNC_EXIT; + dst_p++; + } + } + JERRY_ASSERT (dst_p == byte_code_p + length); + +#if JERRY_LINE_INFO + uint8_t *line_info_p = parser_line_info_generate (context_p); +#endif /* JERRY_LINE_INFO */ + + parse_update_branches (context_p, byte_code_p); + + parser_cbc_stream_free (&context_p->byte_code); + + if (context_p->status_flags & PARSER_HAS_LATE_LIT_INIT) + { + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + uint16_t register_count = context_p->register_count; + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) + { + if ((literal_p->status_flags & LEXER_FLAG_LATE_INIT) && literal_p->prop.index >= register_count) + { + uint32_t source_data = literal_p->u.source_data; + const uint8_t *char_p = context_p->source_end_p - (source_data & 0xfffff); + ecma_value_t lit_value = ecma_find_or_create_literal_string (char_p, + source_data >> 20, + (literal_p->status_flags & LEXER_FLAG_ASCII) != 0); + literal_pool_p[literal_p->prop.index] = lit_value; + } + } + } + + ecma_value_t *base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size); + + if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) + { + parser_list_iterator_t literal_iterator; + uint16_t argument_count = 0; + uint16_t register_count = context_p->register_count; + base_p -= context_p->argument_count; + + parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); + while (argument_count < context_p->argument_count) + { + lexer_literal_t *literal_p; + literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator); + + JERRY_ASSERT (literal_p != NULL); + + if (!(literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)) + { + continue; + } + + /* All arguments must be moved to initialized registers. */ + if (literal_p->type == LEXER_UNUSED_LITERAL) + { + base_p[argument_count] = ECMA_VALUE_EMPTY; + argument_count++; + continue; + } + + JERRY_ASSERT (literal_p->type == LEXER_IDENT_LITERAL); + + JERRY_ASSERT (literal_p->prop.index >= register_count); + + base_p[argument_count] = literal_pool_p[literal_p->prop.index]; + argument_count++; + } + } + + if (!(context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)) + { + *(--base_p) = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_TAGGED_LITERALS; + *(--base_p) = (ecma_value_t) context_p->tagged_template_literal_cp; + } + +#if JERRY_LINE_INFO + ECMA_SET_INTERNAL_VALUE_POINTER (base_p[-1], line_info_p); +#endif /* JERRY_LINE_INFO */ + + if (extended_info != 0) + { +#if JERRY_LINE_INFO + base_p--; +#endif /* JERRY_LINE_INFO */ + + uint8_t *extended_info_p = ((uint8_t *) base_p) - 1; + + compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_EXTENDED_INFO; + *extended_info_p = extended_info; + + if (context_p->argument_length != UINT16_MAX) + { + ecma_extended_info_encode_vlq (&extended_info_p, context_p->argument_length); + } + +#if JERRY_FUNCTION_TO_STRING + if (context_p->last_context_p != NULL) + { + const uint8_t *start_p = context_p->source_start_p; + + if (extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS) + { + start_p = context_p->arguments_start_p; + } + + const uint8_t *function_start_p = context_p->last_context_p->function_start_p; + + ecma_extended_info_encode_vlq (&extended_info_p, (uint32_t) (function_start_p - start_p)); + ecma_extended_info_encode_vlq (&extended_info_p, (uint32_t) (context_p->function_end_p - function_start_p)); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + util_print_cbc (compiled_code_p); + JERRY_DEBUG_MSG ("\nByte code size: %d bytes\n", (int) length); + context_p->total_byte_code_size += (uint32_t) length; + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + return compiled_code_p; +} /* parser_post_processing */ + +#undef PARSER_NEXT_BYTE +#undef PARSER_NEXT_BYTE_UPDATE + +/** + * Resolve private identifier in direct eval context + */ +static bool +parser_resolve_private_identifier_eval (parser_context_t *context_p) /**< context */ +{ + ecma_string_t *search_key_p; + uint8_t *destination_p = (uint8_t *) parser_malloc (context_p, context_p->token.lit_location.length); + + lexer_convert_ident_to_cesu8 (destination_p, + context_p->token.lit_location.char_p, + context_p->token.lit_location.length); + + search_key_p = ecma_new_ecma_string_from_utf8 (destination_p, context_p->token.lit_location.length); + + parser_free (destination_p, context_p->token.lit_location.length); + + ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + + while (true) + { + JERRY_ASSERT (lex_env_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) != 0 + && !ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_object_t *class_object_p = ((ecma_lexical_environment_class_t *) lex_env_p)->object_p; + + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p != NULL) + { + ecma_value_t *collection_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + current_p++; /* skip kind */ + ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++); + current_p++; /* skip value */ + + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + ecma_string_t *private_key_desc_p = + ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor); + + if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p)) + { + ecma_deref_ecma_string (search_key_p); + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return true; + } + } + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + ecma_deref_ecma_string (search_key_p); + return false; +} /* parser_resolve_private_identifier_eval */ + +/** + * Resolve private identifier + */ +void +parser_resolve_private_identifier (parser_context_t *context_p) /**< context */ +{ + if ((context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL) && parser_resolve_private_identifier_eval (context_p)) + { + return; + } + + parser_private_context_t *context_iter_p = context_p->private_context_p; + + while (context_iter_p) + { + if (context_iter_p == NULL || !(context_iter_p->opts & SCANNER_PRIVATE_FIELD_ACTIVE)) + { + parser_raise_error (context_p, PARSER_ERR_UNDECLARED_PRIVATE_FIELD); + } + + if (!(context_iter_p->opts & SCANNER_SUCCESSFUL_CLASS_SCAN)) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return; + } + + parser_private_context_t *private_context_p = context_iter_p; + + if (private_context_p == NULL) + { + parser_raise_error (context_p, PARSER_ERR_UNDECLARED_PRIVATE_FIELD); + } + + scanner_class_private_member_t *ident_iter = private_context_p->members_p; + + while (ident_iter) + { + if (lexer_compare_identifiers (context_p, &context_p->token.lit_location, &ident_iter->loc)) + { + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); + return; + } + + ident_iter = ident_iter->prev_p; + } + + context_iter_p = context_iter_p->prev_p; + } + + parser_raise_error (context_p, PARSER_ERR_UNDECLARED_PRIVATE_FIELD); +} /* parser_resolve_private_identifier */ + +/** + * Save private field context + */ +void +parser_save_private_context (parser_context_t *context_p, /**< context */ + parser_private_context_t *private_ctx_p, /**< private context */ + scanner_class_info_t *class_info_p) /**< class scanner info */ +{ + private_ctx_p->prev_p = context_p->private_context_p; + context_p->private_context_p = private_ctx_p; + + context_p->private_context_p->members_p = class_info_p->members; + context_p->private_context_p->opts = class_info_p->info.u8_arg; + class_info_p->members = NULL; +} /* parser_save_private_context */ + +/** + * Release contexts private fields + */ +static void +parser_free_private_fields (parser_context_t *context_p) /**< context */ +{ + parser_private_context_t *iter = context_p->private_context_p; + + while (iter != NULL) + { + parser_private_context_t *prev_p = iter->prev_p; + scanner_release_private_fields (iter->members_p); + iter = prev_p; + } +} /* parser_free_private_fields */ + +/** + * Restore contexts private fields + */ +void +parser_restore_private_context (parser_context_t *context_p, /**< context */ + parser_private_context_t *private_ctx_p) /**< private context */ +{ + scanner_release_private_fields (context_p->private_context_p->members_p); + context_p->private_context_p = private_ctx_p->prev_p; +} /* parser_restore_private_context */ + +/** + * Free identifiers and literals. + */ +static void +parser_free_literals (parser_list_t *literal_pool_p) /**< literals */ +{ + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + + parser_list_iterator_init (literal_pool_p, &literal_iterator); + while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + util_free_literal (literal_p); + } + + parser_list_free (literal_pool_p); +} /* parser_free_literals */ + +/** + * Parse function arguments + */ +static void +parser_parse_function_arguments (parser_context_t *context_p, /**< context */ + lexer_token_type_t end_type) /**< expected end type */ +{ + JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION); + JERRY_ASSERT (!(context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)); + + bool has_duplicated_arg_names = false; + + if (PARSER_IS_NORMAL_ASYNC_FUNCTION (context_p->status_flags)) + { + parser_branch_t branch; + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_TRY_CREATE_CONTEXT, &branch); + parser_stack_push (context_p, &branch, sizeof (parser_branch_t)); + +#ifndef JERRY_NDEBUG + context_p->context_stack_depth = PARSER_TRY_CONTEXT_STACK_ALLOCATION; +#endif /* !JERRY_NDEBUG */ + } + + if (context_p->token.type == end_type) + { + context_p->status_flags &= (uint32_t) ~PARSER_DISALLOW_AWAIT_YIELD; + + if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS); + parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR); + parser_emit_cbc (context_p, CBC_POP); + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY); + return; + } + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + return; + } + + bool has_complex_argument = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT) != 0; + bool is_strict = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_IS_STRICT) != 0; + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS); + scanner_set_active (context_p); + + context_p->status_flags |= PARSER_FUNCTION_IS_PARSING_ARGS; + + while (true) + { + if (context_p->token.type == LEXER_THREE_DOTS) + { + if (context_p->status_flags & PARSER_IS_PROPERTY_SETTER) + { + parser_raise_error (context_p, PARSER_ERR_SETTER_REST_PARAMETER); + } + lexer_next_token (context_p); + + if (has_duplicated_arg_names) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + + context_p->status_flags |= PARSER_FUNCTION_HAS_REST_PARAM | PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT; + } + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + if (has_duplicated_arg_names) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + + context_p->status_flags |= PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT; + + if (!(context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)) + { + parser_emit_cbc_literal (context_p, + CBC_PUSH_LITERAL, + (uint16_t) (PARSER_REGISTER_START + context_p->argument_count)); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_REST_OBJECT); + } + + uint32_t flags = + (PARSER_PATTERN_BINDING | PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_LOCAL | PARSER_PATTERN_ARGUMENTS); + + if (context_p->next_scanner_info_p->source_p == context_p->source_p) + { + if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER) + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER); + } + + if (context_p->argument_length == UINT16_MAX) + { + context_p->argument_length = context_p->argument_count; + } + + flags |= PARSER_PATTERN_TARGET_DEFAULT; + } + else if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS) + { + if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST) + { + flags |= PARSER_PATTERN_HAS_REST_ELEMENT; + } + scanner_release_next (context_p, sizeof (scanner_info_t)); + } + else + { + parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); + } + } + + parser_parse_initializer (context_p, (parser_pattern_flags_t) flags); + + context_p->argument_count++; + if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + if (context_p->token.type != LEXER_COMMA) + { + if (context_p->token.type != end_type) + { + parser_error_msg_t error = + ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED : PARSER_ERR_IDENTIFIER_EXPECTED); + + parser_raise_error (context_p, error); + } + break; + } + + lexer_next_token (context_p); + + if (context_p->token.type == end_type) + { + break; + } + continue; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); + } + + lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL); + + if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS) + { + context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + + if (JERRY_UNLIKELY (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)) + { + if ((context_p->status_flags & PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT) + || (context_p->status_flags & PARSER_IS_ARROW_FUNCTION)) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + has_duplicated_arg_names = true; + + context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + else + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT; + } + + lexer_next_token (context_p); + + uint16_t literal_index = context_p->lit_object.index; + + if (context_p->token.type == LEXER_ASSIGN) + { + JERRY_ASSERT (has_complex_argument); + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER); + } + + if (context_p->argument_length == UINT16_MAX) + { + context_p->argument_length = context_p->argument_count; + } + + parser_branch_t skip_init; + + if (has_duplicated_arg_names) + { + parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES); + } + + context_p->status_flags |= PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT; + + /* LEXER_ASSIGN does not overwrite lit_object. */ + parser_emit_cbc_literal (context_p, + CBC_PUSH_LITERAL, + (uint16_t) (PARSER_REGISTER_START + context_p->argument_count)); + parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init); + + lexer_next_token (context_p); + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + parser_set_branch_to_current_position (context_p, &skip_init); + + uint16_t opcode = CBC_ASSIGN_LET_CONST; + + if (literal_index >= PARSER_REGISTER_START) + { + opcode = CBC_MOV_IDENT; + } + else if (!scanner_literal_is_created (context_p, literal_index)) + { + opcode = CBC_INIT_ARG_OR_CATCH; + } + + parser_emit_cbc_literal (context_p, opcode, literal_index); + } + else if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_REST_OBJECT); + + uint16_t opcode = CBC_MOV_IDENT; + + if (literal_index < PARSER_REGISTER_START) + { + opcode = CBC_INIT_ARG_OR_CATCH; + + if (scanner_literal_is_created (context_p, literal_index)) + { + opcode = CBC_ASSIGN_LET_CONST; + } + } + + parser_emit_cbc_literal (context_p, opcode, literal_index); + } + else if (has_complex_argument && literal_index < PARSER_REGISTER_START) + { + uint16_t opcode = CBC_INIT_ARG_OR_FUNC; + + if (scanner_literal_is_created (context_p, literal_index)) + { + opcode = CBC_ASSIGN_LET_CONST_LITERAL; + } + + parser_emit_cbc_literal_value (context_p, + opcode, + (uint16_t) (PARSER_REGISTER_START + context_p->argument_count), + literal_index); + } + + context_p->argument_count++; + if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED); + } + + if (context_p->token.type != LEXER_COMMA) + { + if (context_p->token.type != end_type) + { + parser_error_msg_t error = + ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED : PARSER_ERR_IDENTIFIER_EXPECTED); + + parser_raise_error (context_p, error); + } + break; + } + + if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_raise_error (context_p, PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER); + } + + lexer_next_token (context_p); + + if (context_p->token.type == end_type) + { + break; + } + } + + scanner_revert_active (context_p); + + JERRY_ASSERT (has_complex_argument || !(context_p->status_flags & PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT)); + + if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR); + parser_emit_cbc (context_p, CBC_POP); + } + + if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + { + if ((context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_LEXICAL_ENV_NEEDED) + || scanner_is_context_needed (context_p, PARSER_CHECK_FUNCTION_CONTEXT)) + { + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + + parser_branch_t branch; + parser_emit_cbc_forward_branch (context_p, CBC_BLOCK_CREATE_CONTEXT, &branch); + parser_stack_push (context_p, &branch, sizeof (parser_branch_t)); + +#ifndef JERRY_NDEBUG + PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); +#endif /* !JERRY_NDEBUG */ + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED; + } + } + + context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_AWAIT_YIELD | PARSER_FUNCTION_IS_PARSING_ARGS); + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY); + + if (is_strict) + { + context_p->status_flags |= PARSER_IS_STRICT; + } +} /* parser_parse_function_arguments */ + +#ifndef JERRY_NDEBUG +JERRY_STATIC_ASSERT ((PARSER_SCANNING_SUCCESSFUL == PARSER_HAS_LATE_LIT_INIT), + parser_scanning_successful_should_share_the_bit_position_with_parser_has_late_lit_init); +#endif /* !JERRY_NDEBUG */ + +/** + * Parser script size + */ +static size_t +parser_script_size (parser_context_t *context_p) /**< context */ +{ + size_t script_size = sizeof (cbc_script_t); + + if (context_p->user_value != ECMA_VALUE_EMPTY) + { + script_size += sizeof (ecma_value_t); + } + +#if JERRY_FUNCTION_TO_STRING + if (context_p->argument_list != ECMA_VALUE_EMPTY) + { + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + +#if JERRY_MODULE_SYSTEM + if (context_p->global_status_flags & ECMA_PARSE_INTERNAL_HAS_IMPORT_META) + { + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_MODULE_SYSTEM */ + return script_size; +} /* parser_script_size */ + +#if JERRY_SOURCE_NAME +/** + * Parser resource name + */ +static ecma_value_t +parser_source_name (parser_context_t *context_p) /**< context */ +{ + if (context_p->options_p != NULL && (context_p->options_p->options & JERRY_PARSE_HAS_SOURCE_NAME)) + { + JERRY_ASSERT (ecma_is_value_string (context_p->options_p->source_name)); + + ecma_ref_ecma_string (ecma_get_string_from_value (context_p->options_p->source_name)); + return context_p->options_p->source_name; + } + + if (context_p->global_status_flags & ECMA_PARSE_EVAL) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_EVAL); + } + + return ecma_make_magic_string_value (LIT_MAGIC_STRING_SOURCE_NAME_ANON); +} /* parser_source_name */ +#endif /* JERRY_SOURCE_NAME */ + +/** + * Parse and compile EcmaScript source code + * + * Note: source must be a valid UTF-8 string + * + * @return compiled code + */ +static ecma_compiled_code_t * +parser_parse_source (void *source_p, /**< source code */ + uint32_t parse_opts, /**< ecma_parse_opts_t option bits */ + const jerry_parse_options_t *options_p) /**< additional configuration options */ +{ + parser_context_t context; + ecma_compiled_code_t *compiled_code_p; + + context.error = PARSER_ERR_NO_ERROR; + context.status_flags = parse_opts & PARSER_STRICT_MODE_MASK; + context.global_status_flags = parse_opts; + + context.status_flags |= PARSER_RESTORE_STATUS_FLAGS (parse_opts); + context.tagged_template_literal_cp = JMEM_CP_NULL; + + context.stack_depth = 0; + context.stack_limit = 0; + context.options_p = options_p; + context.script_p = NULL; + context.arguments_start_p = NULL; + context.arguments_size = 0; +#if JERRY_MODULE_SYSTEM + if (context.global_status_flags & ECMA_PARSE_MODULE) + { + context.status_flags |= PARSER_IS_STRICT; + } + + context.module_names_p = NULL; +#endif /* JERRY_MODULE_SYSTEM */ + + context.argument_list = ECMA_VALUE_EMPTY; + + if (context.options_p != NULL && (context.options_p->options & JERRY_PARSE_HAS_ARGUMENT_LIST)) + { + context.argument_list = context.options_p->argument_list; + } + else if (context.global_status_flags & ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE) + { + JERRY_ASSERT (context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE); + context.argument_list = ((ecma_value_t *) source_p)[1]; + } + + if (context.argument_list != ECMA_VALUE_EMPTY) + { + JERRY_ASSERT (ecma_is_value_string (context.argument_list)); + + context.status_flags |= PARSER_IS_FUNCTION; + + if (parse_opts & ECMA_PARSE_GENERATOR_FUNCTION) + { + context.status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + if (parse_opts & ECMA_PARSE_ASYNC_FUNCTION) + { + context.status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + + ecma_string_t *string_p = ecma_get_string_from_value (context.argument_list); + uint8_t flags = ECMA_STRING_FLAG_EMPTY; + + context.arguments_start_p = ecma_string_get_chars (string_p, &context.arguments_size, NULL, NULL, &flags); + + if (flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + context.global_status_flags |= ECMA_PARSE_INTERNAL_FREE_ARG_LIST; + } + } + + if (!(context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE)) + { + context.source_start_p = ((parser_source_char_t *) source_p)->source_p; + context.source_size = (lit_utf8_size_t) ((parser_source_char_t *) source_p)->source_size; + } + else + { + ecma_value_t source = ((ecma_value_t *) source_p)[0]; + + JERRY_ASSERT (ecma_is_value_string (source)); + + ecma_string_t *string_p = ecma_get_string_from_value (source); + uint8_t flags = ECMA_STRING_FLAG_EMPTY; + + context.source_start_p = ecma_string_get_chars (string_p, &context.source_size, NULL, NULL, &flags); + + if (flags & ECMA_STRING_FLAG_MUST_BE_FREED) + { + context.global_status_flags |= ECMA_PARSE_INTERNAL_FREE_SOURCE; + } + } + + context.user_value = ECMA_VALUE_EMPTY; + + if ((context.global_status_flags & ECMA_PARSE_EVAL) && JERRY_CONTEXT (vm_top_context_p) != NULL) + { + const ecma_compiled_code_t *bytecode_header_p = JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p; + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + ecma_value_t parent_script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + ; + cbc_script_t *parent_script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, parent_script_value); + + if (parent_script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE) + { + context.user_value = CBC_SCRIPT_GET_USER_VALUE (parent_script_p); + } +#if JERRY_SNAPSHOT_EXEC + } +#endif /* JERRY_SNAPSHOT_EXEC */ + } + else if (context.options_p != NULL && (context.options_p->options & JERRY_PARSE_HAS_USER_VALUE)) + { + context.user_value = context.options_p->user_value; + } + + context.last_context_p = NULL; + context.last_statement.current_p = NULL; + context.token.flags = 0; + lexer_init_line_info (&context); + + scanner_info_t scanner_info_end; + scanner_info_end.next_p = NULL; + scanner_info_end.source_p = NULL; + scanner_info_end.type = SCANNER_TYPE_END; + context.next_scanner_info_p = &scanner_info_end; + context.active_scanner_info_p = NULL; + context.skipped_scanner_info_p = NULL; + context.skipped_scanner_info_end_p = NULL; + + context.last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + + context.argument_count = 0; + context.argument_length = UINT16_MAX; + context.register_count = 0; + context.literal_count = 0; + + parser_cbc_stream_init (&context.byte_code); + context.byte_code_size = 0; + parser_list_init (&context.literal_pool, + sizeof (lexer_literal_t), + (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_literal_t))); + context.scope_stack_p = NULL; + context.scope_stack_size = 0; + context.scope_stack_top = 0; + context.scope_stack_reg_top = 0; + context.scope_stack_global_end = 0; + context.tagged_template_literal_cp = JMEM_CP_NULL; + context.private_context_p = NULL; + +#ifndef JERRY_NDEBUG + context.context_stack_depth = 0; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + context.line_info_p = NULL; +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + context.function_start_p = NULL; + context.function_end_p = NULL; +#endif /* JERRY_FUNCTION_TO_STRING */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + context.is_show_opcodes = (JERRY_CONTEXT (jerry_init_flags) & JERRY_INIT_SHOW_OPCODES); + context.total_byte_code_size = 0; + + if (context.is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n", (context.arguments_start_p == NULL) ? "Script" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scanner_scan_all (&context); + + if (JERRY_UNLIKELY (context.error != PARSER_ERR_NO_ERROR)) + { + JERRY_ASSERT (context.error == PARSER_ERR_OUT_OF_MEMORY); + + /* It is unlikely that memory can be allocated in an out-of-memory + * situation. However, a simple value can still be thrown. */ + jcontext_raise_exception (ECMA_VALUE_NULL); + return NULL; + } + + if (context.arguments_start_p == NULL) + { + context.source_p = context.source_start_p; + context.source_end_p = context.source_start_p + context.source_size; + } + else + { + context.source_p = context.arguments_start_p; + context.source_end_p = context.arguments_start_p + context.arguments_size; + } + + context.u.allocated_buffer_p = NULL; + context.token.flags = 0; + lexer_init_line_info (&context); + + parser_stack_init (&context); + + JERRY_ASSERT (context.next_scanner_info_p->source_p == context.source_p); + JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + if (context.next_scanner_info_p->u8_arg & SCANNER_FUNCTION_IS_STRICT) + { + context.status_flags |= PARSER_IS_STRICT; + } + + PARSER_TRY (context.try_buffer) + { + context.script_p = (cbc_script_t *) parser_malloc (&context, parser_script_size (&context)); + + CBC_SCRIPT_SET_TYPE (context.script_p, context.user_value, CBC_SCRIPT_REF_ONE); + + if (context.global_status_flags & (ECMA_PARSE_EVAL | ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE)) + { + context.script_p->refs_and_type |= CBC_SCRIPT_IS_EVAL_CODE; + } + +#if JERRY_BUILTIN_REALMS + context.script_p->realm_p = (ecma_object_t *) JERRY_CONTEXT (global_object_p); +#endif /* JERRY_BUILTIN_REALMS */ + +#if JERRY_SOURCE_NAME + context.script_p->source_name = parser_source_name (&context); +#endif /* JERRY_SOURCE_NAME */ + + ECMA_SET_INTERNAL_VALUE_POINTER (context.script_value, context.script_p); + + /* Pushing a dummy value ensures the stack is never empty. + * This simplifies the stack management routines. */ + parser_stack_push_uint8 (&context, CBC_MAXIMUM_BYTE_VALUE); + /* The next token must always be present to make decisions + * in the parser. Therefore when a token is consumed, the + * lexer_next_token() must be immediately called. */ + lexer_next_token (&context); + + if (context.arguments_start_p != NULL) + { + parser_parse_function_arguments (&context, LEXER_EOS); + + JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS); + scanner_release_next (&context, sizeof (scanner_info_t)); + + context.source_p = context.source_start_p; + context.source_end_p = context.source_start_p + context.source_size; + lexer_init_line_info (&context); + + lexer_next_token (&context); + } +#if JERRY_MODULE_SYSTEM + else if (parse_opts & ECMA_PARSE_MODULE) + { + parser_branch_t branch; + parser_emit_cbc_forward_branch (&context, CBC_JUMP_FORWARD, &branch); + + scanner_create_variables (&context, SCANNER_CREATE_VARS_IS_MODULE); + parser_emit_cbc (&context, CBC_RETURN_FUNCTION_END); + + parser_set_branch_to_current_position (&context, &branch); + } +#endif /* JERRY_MODULE_SYSTEM */ + else + { + JERRY_ASSERT (context.next_scanner_info_p->source_p == context.source_start_p + && context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); + + if (scanner_is_context_needed (&context, PARSER_CHECK_GLOBAL_CONTEXT)) + { + context.status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + + if (!(parse_opts & ECMA_PARSE_EVAL)) + { + scanner_check_variables (&context); + } + + scanner_create_variables (&context, SCANNER_CREATE_VARS_IS_SCRIPT); + } + + parser_parse_statements (&context); + + JERRY_ASSERT (context.last_statement.current_p == NULL); + + JERRY_ASSERT (context.last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + JERRY_ASSERT (context.u.allocated_buffer_p == NULL); + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (context.status_flags & PARSER_SCANNING_SUCCESSFUL); + JERRY_ASSERT (!(context.global_status_flags & ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR)); + context.status_flags &= (uint32_t) ~PARSER_SCANNING_SUCCESSFUL; +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (!(context.status_flags & PARSER_HAS_LATE_LIT_INIT)); + + compiled_code_p = parser_post_processing (&context); + parser_list_free (&context.literal_pool); + + /* When parsing is successful, only the dummy value can be remained on the stack. */ + JERRY_ASSERT (context.stack_top_uint8 == CBC_MAXIMUM_BYTE_VALUE && context.stack.last_position == 1 + && context.stack.first_p != NULL && context.stack.first_p->next_p == NULL + && context.stack.last_p == NULL); + + JERRY_ASSERT (context.arguments_start_p != NULL || !(context.status_flags & PARSER_ARGUMENTS_NEEDED)); + + context.script_p->refs_and_type -= CBC_SCRIPT_REF_ONE; + + if (context.user_value != ECMA_VALUE_EMPTY) + { + CBC_SCRIPT_GET_USER_VALUE (context.script_p) = ecma_copy_value_if_not_object (context.user_value); + } + +#if JERRY_MODULE_SYSTEM + if (context.global_status_flags & ECMA_PARSE_INTERNAL_HAS_IMPORT_META) + { + int idx = (context.user_value != ECMA_VALUE_EMPTY) ? 1 : 0; + ecma_value_t module = ecma_make_object_value ((ecma_object_t *) JERRY_CONTEXT (module_current_p)); + + CBC_SCRIPT_GET_OPTIONAL_VALUES (context.script_p)[idx] = module; + context.script_p->refs_and_type |= CBC_SCRIPT_HAS_IMPORT_META; + } +#endif /* JERRY_MODULE_SYSTEM */ + +#if JERRY_FUNCTION_TO_STRING + if (!(context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE)) + { + ecma_string_t *string_p; + + if (context.global_status_flags & ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER) + { + string_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (context.source_start_p, context.source_size); + } + else + { + string_p = ecma_new_ecma_string_from_utf8 (context.source_start_p, context.source_size); + } + + context.script_p->source_code = ecma_make_string_value (string_p); + } + else + { + ecma_value_t source = ((ecma_value_t *) source_p)[0]; + + ecma_ref_ecma_string (ecma_get_string_from_value (source)); + context.script_p->source_code = source; + } + + if (context.argument_list != ECMA_VALUE_EMPTY) + { + int idx = (context.user_value != ECMA_VALUE_EMPTY) ? 1 : 0; + + CBC_SCRIPT_GET_OPTIONAL_VALUES (context.script_p)[idx] = context.argument_list; + + ecma_ref_ecma_string (ecma_get_string_from_value (context.argument_list)); + context.script_p->refs_and_type |= CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS; + } +#endif /* JERRY_FUNCTION_TO_STRING */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context.is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n%s parsing successfully completed. Total byte code size: %d bytes\n", + (context.arguments_start_p == NULL) ? "Script" : "Function", + (int) context.total_byte_code_size); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + } + PARSER_CATCH + { + if (context.last_statement.current_p != NULL) + { + parser_free_jumps (context.last_statement); + } + + parser_free_allocated_buffer (&context); + + scanner_cleanup (&context); + +#if JERRY_MODULE_SYSTEM + if (context.module_names_p != NULL) + { + ecma_module_release_module_names (context.module_names_p); + } +#endif /* JERRY_MODULE_SYSTEM */ + + compiled_code_p = NULL; + parser_free_literals (&context.literal_pool); + parser_cbc_stream_free (&context.byte_code); + +#if JERRY_SOURCE_NAME + ecma_deref_ecma_string (ecma_get_string_from_value (context.script_p->source_name)); +#endif /* JERRY_SOURCE_NAME */ + + if (context.script_p != NULL) + { + JERRY_ASSERT (context.script_p->refs_and_type >= CBC_SCRIPT_REF_ONE); + jmem_heap_free_block (context.script_p, parser_script_size (&context)); + } + } + PARSER_TRY_END + + if (context.scope_stack_p != NULL) + { + parser_free (context.scope_stack_p, context.scope_stack_size * sizeof (parser_scope_stack_t)); + } + +#if JERRY_LINE_INFO + parser_line_info_free (context.line_info_p); +#endif /* JERRY_LINE_INFO */ + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context.is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n", (context.arguments_start_p == NULL) ? "Script" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_stack_free (&context); + + if (context.global_status_flags & ECMA_PARSE_INTERNAL_FREE_SOURCE) + { + jmem_heap_free_block ((void *) context.source_start_p, context.source_size); + } + + if (context.global_status_flags & ECMA_PARSE_INTERNAL_FREE_ARG_LIST) + { + jmem_heap_free_block ((void *) context.arguments_start_p, context.arguments_size); + } + + if (compiled_code_p != NULL) + { + return compiled_code_p; + } + + if (context.error == PARSER_ERR_OUT_OF_MEMORY) + { + /* It is unlikely that memory can be allocated in an out-of-memory + * situation. However, a simple value can still be thrown. */ + jcontext_raise_exception (ECMA_VALUE_NULL); + return NULL; + } +#if (JERRY_STACK_LIMIT != 0) + if (context.error == PARSER_ERR_STACK_OVERFLOW) + { + ecma_raise_standard_error (JERRY_ERROR_RANGE, ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED); + return NULL; + } +#endif /* JERRY_STACK_LIMIT != 0 */ + +#if JERRY_ERROR_MESSAGES + ecma_string_t *err_str_p; + + if (context.error == PARSER_ERR_INVALID_REGEXP) + { + ecma_value_t error = jcontext_take_exception (); + ecma_property_t *prop_p = + ecma_find_named_property (ecma_get_object_from_value (error), ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE)); + ecma_free_value (error); + JERRY_ASSERT (prop_p); + err_str_p = ecma_get_string_from_value (ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_ref_ecma_string (err_str_p); + } + else + { + err_str_p = ecma_new_ecma_external_string_from_cesu8 (parser_get_error_utf8 (context.error), + parser_get_error_size (context.error), + NULL); + } + ecma_value_t err_str_val = ecma_make_string_value (err_str_p); + ecma_value_t line_str_val = ecma_make_uint32_value (context.token.line); + ecma_value_t col_str_val = ecma_make_uint32_value (context.token.column); + ecma_value_t source_name = parser_source_name (&context); + + ecma_raise_standard_error_with_format (JERRY_ERROR_SYNTAX, + "% [%:%:%]", + err_str_val, + source_name, + line_str_val, + col_str_val); + + ecma_free_value (source_name); + ecma_free_value (col_str_val); + ecma_free_value (line_str_val); + ecma_deref_ecma_string (err_str_p); +#else /* !JERRY_ERROR_MESSAGES */ + if (context.error == PARSER_ERR_INVALID_REGEXP) + { + jcontext_release_exception (); + } + + ecma_raise_syntax_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + + return NULL; +} /* parser_parse_source */ + +/** + * Save parser context before function parsing. + */ +static void +parser_save_context (parser_context_t *context_p, /**< context */ + parser_saved_context_t *saved_context_p) /**< target for saving the context */ +{ + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS) + { + context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + + /* Save private part of the context. */ + + saved_context_p->status_flags = context_p->status_flags; + saved_context_p->stack_depth = context_p->stack_depth; + saved_context_p->stack_limit = context_p->stack_limit; + saved_context_p->prev_context_p = context_p->last_context_p; + saved_context_p->last_statement = context_p->last_statement; + + saved_context_p->argument_count = context_p->argument_count; + saved_context_p->argument_length = context_p->argument_length; + saved_context_p->register_count = context_p->register_count; + saved_context_p->literal_count = context_p->literal_count; + + saved_context_p->byte_code = context_p->byte_code; + saved_context_p->byte_code_size = context_p->byte_code_size; + saved_context_p->literal_pool_data = context_p->literal_pool.data; + saved_context_p->scope_stack_p = context_p->scope_stack_p; + saved_context_p->scope_stack_size = context_p->scope_stack_size; + saved_context_p->scope_stack_top = context_p->scope_stack_top; + saved_context_p->scope_stack_reg_top = context_p->scope_stack_reg_top; + saved_context_p->scope_stack_global_end = context_p->scope_stack_global_end; + saved_context_p->tagged_template_literal_cp = context_p->tagged_template_literal_cp; + +#ifndef JERRY_NDEBUG + saved_context_p->context_stack_depth = context_p->context_stack_depth; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + saved_context_p->line_info_p = context_p->line_info_p; +#endif /* JERRY_LINE_INFO */ + +#if JERRY_FUNCTION_TO_STRING + saved_context_p->function_start_p = context_p->function_start_p; +#endif /* JERRY_FUNCTION_TO_STRING */ + + /* Reset private part of the context. */ + + context_p->status_flags &= PARSER_IS_STRICT; + context_p->stack_depth = 0; + context_p->stack_limit = 0; + context_p->last_context_p = saved_context_p; + context_p->last_statement.current_p = NULL; + + context_p->argument_count = 0; + context_p->argument_length = UINT16_MAX; + context_p->register_count = 0; + context_p->literal_count = 0; + + parser_cbc_stream_init (&context_p->byte_code); + context_p->byte_code_size = 0; + parser_list_reset (&context_p->literal_pool); + context_p->scope_stack_p = NULL; + context_p->scope_stack_size = 0; + context_p->scope_stack_top = 0; + context_p->scope_stack_reg_top = 0; + context_p->scope_stack_global_end = 0; + context_p->tagged_template_literal_cp = JMEM_CP_NULL; + +#ifndef JERRY_NDEBUG + context_p->context_stack_depth = 0; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + context_p->line_info_p = NULL; +#endif /* JERRY_LINE_INFO */ +} /* parser_save_context */ + +/** + * Restore parser context after function parsing. + */ +static void +parser_restore_context (parser_context_t *context_p, /**< context */ + parser_saved_context_t *saved_context_p) /**< target for saving the context */ +{ + parser_list_free (&context_p->literal_pool); + + if (context_p->scope_stack_p != NULL) + { + parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t)); + } + +#if JERRY_LINE_INFO + parser_line_info_free (context_p->line_info_p); +#endif /* JERRY_LINE_INFO */ + + /* Restore private part of the context. */ + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + context_p->status_flags = saved_context_p->status_flags; + context_p->stack_depth = saved_context_p->stack_depth; + context_p->stack_limit = saved_context_p->stack_limit; + context_p->last_context_p = saved_context_p->prev_context_p; + context_p->last_statement = saved_context_p->last_statement; + + context_p->argument_count = saved_context_p->argument_count; + context_p->argument_length = saved_context_p->argument_length; + context_p->register_count = saved_context_p->register_count; + context_p->literal_count = saved_context_p->literal_count; + + context_p->byte_code = saved_context_p->byte_code; + context_p->byte_code_size = saved_context_p->byte_code_size; + context_p->literal_pool.data = saved_context_p->literal_pool_data; + context_p->scope_stack_p = saved_context_p->scope_stack_p; + context_p->scope_stack_size = saved_context_p->scope_stack_size; + context_p->scope_stack_top = saved_context_p->scope_stack_top; + context_p->scope_stack_reg_top = saved_context_p->scope_stack_reg_top; + context_p->scope_stack_global_end = saved_context_p->scope_stack_global_end; + context_p->tagged_template_literal_cp = saved_context_p->tagged_template_literal_cp; + +#ifndef JERRY_NDEBUG + context_p->context_stack_depth = saved_context_p->context_stack_depth; +#endif /* !JERRY_NDEBUG */ + +#if JERRY_LINE_INFO + context_p->line_info_p = saved_context_p->line_info_p; +#endif /* JERRY_LINE_INFO */ +} /* parser_restore_context */ + +/** + * Parse function code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_function (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< extra status flags */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); + parser_save_context (context_p, &saved_context); + context_p->status_flags |= status_flags; + context_p->status_flags |= PARSER_ALLOW_NEW_TARGET; + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n", + (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIST_EXPECTED); + } + + lexer_next_token (context_p); + + parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN); + lexer_next_token (context_p); + + if ((context_p->status_flags & PARSER_IS_PROPERTY_GETTER) && context_p->argument_count != 0) + { + parser_raise_error (context_p, PARSER_ERR_NO_ARGUMENTS_EXPECTED); + } + + if ((context_p->status_flags & PARSER_IS_PROPERTY_SETTER) && context_p->argument_count != 1) + { + parser_raise_error (context_p, PARSER_ERR_ONE_ARGUMENT_EXPECTED); + } + + if ((context_p->status_flags & (PARSER_CLASS_CONSTRUCTOR | PARSER_ALLOW_SUPER_CALL)) == PARSER_CLASS_CONSTRUCTOR) + { + parser_emit_cbc_ext (context_p, CBC_EXT_RUN_FIELD_INIT); + parser_flush_cbc (context_p); + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes && (context_p->status_flags & PARSER_HAS_NON_STRICT_ARG)) + { + JERRY_DEBUG_MSG (" Note: legacy (non-strict) argument definition\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED); + } + + lexer_next_token (context_p); + parser_parse_statements (context_p); + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n", + (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor" : "Function"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + return compiled_code_p; +} /* parser_parse_function */ + +/** + * Parse static class block code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_class_static_block (parser_context_t *context_p) /**< context */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + parser_save_context (context_p, &saved_context); + context_p->status_flags |= (PARSER_IS_CLASS_STATIC_BLOCK | PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER + | PARSER_INSIDE_CLASS_FIELD | PARSER_ALLOW_NEW_TARGET | PARSER_DISALLOW_AWAIT_YIELD); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Static class block parsing start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); + lexer_next_token (context_p); + + parser_parse_statements (context_p); + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Static class block parsing end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + return compiled_code_p; +} /* parser_parse_class_static_block */ + +/** + * Parse arrow function code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_arrow_function (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< extra status flags */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); + JERRY_ASSERT (status_flags & PARSER_IS_ARROW_FUNCTION); + parser_save_context (context_p, &saved_context); + context_p->status_flags |= status_flags; + context_p->status_flags |= + saved_context.status_flags & (PARSER_ALLOW_NEW_TARGET | PARSER_ALLOW_SUPER | PARSER_ALLOW_SUPER_CALL); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Arrow function parsing start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + /* The `await` keyword is disallowed in the IdentifierReference position */ + if (status_flags & PARSER_IS_CLASS_STATIC_BLOCK) + { + context_p->status_flags |= PARSER_DISALLOW_AWAIT_YIELD; + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + lexer_next_token (context_p); + parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN); + lexer_next_token (context_p); + } + else + { + parser_parse_function_arguments (context_p, LEXER_ARROW); + } + + /* The `await` keyword is interpreted as an identifier within the body of arrow functions */ + if (status_flags & PARSER_IS_CLASS_STATIC_BLOCK) + { + context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_AWAIT_YIELD | PARSER_IS_CLASS_STATIC_BLOCK); + } + + JERRY_ASSERT (context_p->token.type == LEXER_ARROW); + + lexer_next_token (context_p); + bool next_token_needed = false; + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + lexer_next_token (context_p); + + context_p->status_flags |= PARSER_IS_CLOSURE; + parser_parse_statements (context_p); + + /* Unlike normal function, arrow functions consume their close brace. */ + JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE); + next_token_needed = true; + } + else + { + if (context_p->status_flags & PARSER_IS_STRICT && context_p->status_flags & PARSER_HAS_NON_STRICT_ARG) + { + parser_raise_error (context_p, PARSER_ERR_NON_STRICT_ARG_DEFINITION); + } + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL; + } + else + { + parser_emit_cbc (context_p, CBC_RETURN); + } + parser_flush_cbc (context_p); + + lexer_update_await_yield (context_p, saved_context.status_flags); + } + + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Arrow function parsing end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + if (next_token_needed) + { + lexer_next_token (context_p); + } + + return compiled_code_p; +} /* parser_parse_arrow_function */ + +/** + * Parse class fields + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_class_fields (parser_context_t *context_p) /**< context */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + uint32_t extra_status_flags = context_p->status_flags & PARSER_INSIDE_WITH; + + parser_save_context (context_p, &saved_context); + context_p->status_flags |= (PARSER_IS_FUNCTION | PARSER_ALLOW_SUPER | PARSER_INSIDE_CLASS_FIELD + | PARSER_ALLOW_NEW_TARGET | extra_status_flags); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Class fields parsing start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + const uint8_t *source_end_p = context_p->source_end_p; + bool first_computed_class_field = true; + scanner_location_t end_location; + scanner_get_location (&end_location, context_p); + + do + { + uint8_t class_field_type = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + + scanner_range_t range = { 0 }; + + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + parser_stack_pop (context_p, &range, sizeof (scanner_range_t)); + } + else if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + parser_stack_pop (context_p, &range.start_location, sizeof (scanner_location_t)); + } + + uint16_t literal_index = 0; + bool is_private = false; + + if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + scanner_set_location (context_p, &range.start_location); + + if (class_field_type & PARSER_CLASS_FIELD_STATIC_BLOCK) + { + scanner_seek (context_p); + JERRY_ASSERT (context_p->source_p[1] == LIT_CHAR_LEFT_BRACE); + context_p->source_p += 2; + context_p->source_end_p = source_end_p; + + uint16_t func_index = lexer_construct_class_static_block_function (context_p); + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_CLASS_CALL_STATIC_BLOCK, func_index); + continue; + } + + uint32_t ident_opts = LEXER_OBJ_IDENT_ONLY_IDENTIFIERS; + is_private = context_p->source_p[-1] == LIT_CHAR_HASHMARK; + + if (is_private) + { + ident_opts |= LEXER_OBJ_IDENT_CLASS_PRIVATE; + } + + context_p->source_end_p = source_end_p; + scanner_seek (context_p); + + lexer_expect_object_literal_id (context_p, ident_opts); + + literal_index = context_p->lit_object.index; + + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + lexer_next_token (context_p); + JERRY_ASSERT (context_p->token.type == LEXER_ASSIGN); + } + } + else if (first_computed_class_field) + { + parser_emit_cbc (context_p, CBC_PUSH_NUMBER_0); + first_computed_class_field = false; + } + + if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED) + { + if (!(class_field_type & PARSER_CLASS_FIELD_NORMAL)) + { + scanner_set_location (context_p, &range.start_location); + scanner_seek (context_p); + } + + context_p->source_end_p = range.source_end_p; + lexer_next_token (context_p); + +#if JERRY_LINE_INFO + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); +#endif /* JERRY_LINE_INFO */ + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->token.type != LEXER_EOS) + { + parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); + } + } + else + { + parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED); + } + + if (class_field_type & PARSER_CLASS_FIELD_NORMAL) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, literal_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + uint32_t function_name_status_flags = is_private ? PARSER_PRIVATE_FUNCTION_NAME : 0; + parser_set_function_name (context_p, function_literal_index, literal_index, function_name_status_flags); + } + + if (is_private) + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_PRIVATE_FIELD_ADD, literal_index); + } + else + { + parser_emit_cbc_ext_literal (context_p, CBC_EXT_DEFINE_FIELD, literal_index); + } + + /* Prepare stack slot for assignment property reference base. Needed by vm.c */ + if (context_p->stack_limit == context_p->stack_depth) + { + context_p->stack_limit++; + JERRY_ASSERT (context_p->stack_limit <= PARSER_MAXIMUM_STACK_LIMIT); + } + } + else + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + uint16_t opcode = CBC_EXT_SET_NEXT_COMPUTED_FIELD; + + if (function_literal_index < PARSER_NAMED_FUNCTION || function_literal_index == PARSER_ANONYMOUS_CLASS) + { + opcode = CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC; + } + + parser_flush_cbc (context_p); + + /* The next opcode pushes two more temporary values onto the stack */ + if (context_p->stack_depth + 1 > context_p->stack_limit) + { + context_p->stack_limit = (uint16_t) (context_p->stack_depth + 1); + if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT) + { + parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED); + } + } + + parser_emit_cbc_ext (context_p, opcode); + } + } while (!(context_p->stack_top_uint8 & PARSER_CLASS_FIELD_END)); + + if (!first_computed_class_field) + { + parser_emit_cbc (context_p, CBC_POP); + } + + parser_flush_cbc (context_p); + context_p->source_end_p = source_end_p; + scanner_set_location (context_p, &end_location); + +#if JERRY_LINE_INFO + if (context_p->line_info_p == NULL) + { + parser_line_info_append (context_p, context_p->token.line, context_p->token.column); + } +#endif /* JERRY_LINE_INFO */ + + compiled_code_p = parser_post_processing (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Class fields parsing end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + return compiled_code_p; +} /* parser_parse_class_fields */ + +/** + * Check whether the last emitted cbc opcode was an anonymous function declaration + * + * @return PARSER_NOT_FUNCTION_LITERAL - if the last opcode is not a function literal + * PARSER_NAMED_FUNCTION - if the last opcode is not a named function declataion + * PARSER_ANONYMOUS_CLASS - if the last opcode is an anonymous class declaration + * literal index of the anonymous function literal - otherwise + */ +uint16_t +parser_check_anonymous_function_declaration (parser_context_t *context_p) /**< context */ +{ + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS)) + { + return PARSER_ANONYMOUS_CLASS; + } + + if (context_p->last_cbc.literal_type != LEXER_FUNCTION_LITERAL) + { + return PARSER_NOT_FUNCTION_LITERAL; + } + + uint16_t literal_index = PARSER_NOT_FUNCTION_LITERAL; + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + literal_index = context_p->last_cbc.literal_index; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + literal_index = context_p->last_cbc.value; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS) + { + literal_index = context_p->last_cbc.third_literal_index; + } + else + { + return PARSER_NOT_FUNCTION_LITERAL; + } + + const ecma_compiled_code_t *bytecode_p; + bytecode_p = (const ecma_compiled_code_t *) (PARSER_GET_LITERAL (literal_index)->u.bytecode_p); + bool is_anon = + ecma_is_value_magic_string (*ecma_compiled_code_resolve_function_name (bytecode_p), LIT_MAGIC_STRING__EMPTY); + + return (is_anon ? literal_index : PARSER_NAMED_FUNCTION); +} /* parser_check_anonymous_function_declaration */ + +/** + * Set the function name of the function literal corresponds to the given function literal index + * to the given character buffer of literal corresponds to the given name index. + */ +void +parser_set_function_name (parser_context_t *context_p, /**< context */ + uint16_t function_literal_index, /**< function literal index */ + uint16_t name_index, /**< function name literal index */ + uint32_t status_flags) /**< status flags */ +{ + ecma_compiled_code_t *bytecode_p; + bytecode_p = (ecma_compiled_code_t *) (PARSER_GET_LITERAL (function_literal_index)->u.bytecode_p); + + parser_compiled_code_set_function_name (context_p, bytecode_p, name_index, status_flags); +} /* parser_set_function_name */ + +/** + * Prepend the given prefix into the current function name literal + * + * @return pointer to the newly allocated buffer + */ +static uint8_t * +parser_add_function_name_prefix (parser_context_t *context_p, /**< context */ + const char *prefix_p, /**< prefix */ + uint32_t prefix_size, /**< prefix's length */ + uint32_t *name_length_p, /**< [out] function name's size */ + lexer_literal_t *name_lit_p) /**< function name literal */ +{ + *name_length_p += prefix_size; + uint8_t *name_buffer_p = (uint8_t *) parser_malloc (context_p, *name_length_p * sizeof (uint8_t)); + memcpy (name_buffer_p, prefix_p, prefix_size); + memcpy (name_buffer_p + prefix_size, name_lit_p->u.char_p, name_lit_p->prop.length); + + return name_buffer_p; +} /* parser_add_function_name_prefix */ + +/** + * Set the function name of the given compiled code + * to the given character buffer of literal corresponds to the given name index. + */ +void +parser_compiled_code_set_function_name (parser_context_t *context_p, /**< context */ + ecma_compiled_code_t *bytecode_p, /**< function literal index */ + uint16_t name_index, /**< function name literal index */ + uint32_t status_flags) /**< status flags */ +{ + ecma_value_t *func_name_start_p; + func_name_start_p = ecma_compiled_code_resolve_function_name ((const ecma_compiled_code_t *) bytecode_p); + + if (JERRY_UNLIKELY (!ecma_is_value_magic_string (*func_name_start_p, LIT_MAGIC_STRING__EMPTY))) + { + return; + } + + parser_scope_stack_t *scope_stack_start_p = context_p->scope_stack_p; + parser_scope_stack_t *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top; + + while (scope_stack_p > scope_stack_start_p) + { + scope_stack_p--; + + if (scope_stack_p->map_from != PARSER_SCOPE_STACK_FUNC && scanner_decode_map_to (scope_stack_p) == name_index) + { + name_index = scope_stack_p->map_from; + break; + } + } + + lexer_literal_t *name_lit_p = (lexer_literal_t *) PARSER_GET_LITERAL (name_index); + + if (name_lit_p->type != LEXER_IDENT_LITERAL && name_lit_p->type != LEXER_STRING_LITERAL) + { + return; + } + + uint8_t *name_buffer_p = (uint8_t *) name_lit_p->u.char_p; + uint32_t name_length = name_lit_p->prop.length; + + if (status_flags & PARSER_PRIVATE_FUNCTION_NAME) + { + name_buffer_p = parser_add_function_name_prefix (context_p, "#", 1, &name_length, name_lit_p); + } + else if (status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER)) + { + name_buffer_p = parser_add_function_name_prefix (context_p, + (status_flags & PARSER_IS_PROPERTY_GETTER) ? "get " : "set ", + 4, + &name_length, + name_lit_p); + } + + *func_name_start_p = + ecma_find_or_create_literal_string (name_buffer_p, name_length, (status_flags & LEXER_FLAG_ASCII) != 0); + + if (name_buffer_p != name_lit_p->u.char_p) + { + parser_free (name_buffer_p, name_length); + } +} /* parser_compiled_code_set_function_name */ + +/** + * Raise a parse error. + */ +void +parser_raise_error (parser_context_t *context_p, /**< context */ + parser_error_msg_t error) /**< error code */ +{ + /* Must be compatible with the scanner because + * the lexer might throws errors during prescanning. */ + parser_saved_context_t *saved_context_p = context_p->last_context_p; + + while (saved_context_p != NULL) + { + parser_cbc_stream_free (&saved_context_p->byte_code); + + /* First the current literal pool is freed, and then it is replaced + * by the literal pool coming from the saved context. Since literals + * are not used anymore, this is a valid replacement. The last pool + * is freed by parser_parse_source. */ + + parser_free_literals (&context_p->literal_pool); + context_p->literal_pool.data = saved_context_p->literal_pool_data; + + if (context_p->scope_stack_p != NULL) + { + parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t)); + } + context_p->scope_stack_p = saved_context_p->scope_stack_p; + context_p->scope_stack_size = saved_context_p->scope_stack_size; + + if (saved_context_p->last_statement.current_p != NULL) + { + parser_free_jumps (saved_context_p->last_statement); + } + + if (saved_context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + ecma_collection_t *collection = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, saved_context_p->tagged_template_literal_cp); + ecma_collection_free_template_literal (collection); + } + +#if JERRY_LINE_INFO + parser_line_info_free (saved_context_p->line_info_p); +#endif /* JERRY_LINE_INFO */ + + saved_context_p = saved_context_p->prev_context_p; + } + + parser_free_private_fields (context_p); + + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + ecma_collection_t *collection = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_p->tagged_template_literal_cp); + ecma_collection_free_template_literal (collection); + } + + context_p->error = error; + PARSER_THROW (context_p->try_buffer); + /* Should never been reached. */ + JERRY_ASSERT (0); +} /* parser_raise_error */ + +#endif /* JERRY_PARSER */ + +/** + * Parse EcmaScript source code + * + * Note: + * if arg_list_p is not NULL, a function body is parsed + * returned value must be freed with ecma_free_value + * + * @return pointer to compiled byte code - if success + * NULL - otherwise + */ +ecma_compiled_code_t * +parser_parse_script (void *source_p, /**< source code */ + uint32_t parse_opts, /**< ecma_parse_opts_t option bits */ + const jerry_parse_options_t *options_p) /**< additional configuration options */ +{ +#if JERRY_PARSER + ecma_compiled_code_t *bytecode_p = parser_parse_source (source_p, parse_opts, options_p); + + if (JERRY_UNLIKELY (bytecode_p == NULL)) + { + /* Exception has already thrown. */ + return NULL; + } + + return bytecode_p; +#else /* !JERRY_PARSER */ + JERRY_UNUSED (arg_list_p); + JERRY_UNUSED (arg_list_size); + JERRY_UNUSED (source_p); + JERRY_UNUSED (source_size); + JERRY_UNUSED (parse_opts); + JERRY_UNUSED (source_name); + + ecma_raise_syntax_error (ECMA_ERR_PARSER_NOT_SUPPORTED); + return NULL; +#endif /* JERRY_PARSER */ +} /* parser_parse_script */ + +/** + * @} + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.h new file mode 100644 index 00000000..59238d54 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-parser.h @@ -0,0 +1,40 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_PARSER_H +#define JS_PARSER_H + +#include "ecma-globals.h" + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_parser Parser + * @{ + */ + +/* Note: source must be a valid UTF-8 string */ +ecma_compiled_code_t *parser_parse_script (void *source_p, uint32_t parse_opts, const jerry_parse_options_t *options_p); + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_PARSER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-internal.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-internal.h new file mode 100644 index 00000000..128f401f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-internal.h @@ -0,0 +1,399 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_SCANNER_INTERNAL_H +#define JS_SCANNER_INTERNAL_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Scan mode types. + */ +typedef enum +{ + SCAN_MODE_PRIMARY_EXPRESSION, /**< scanning primary expression */ + SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW, /**< scanning primary expression after new */ + SCAN_MODE_POST_PRIMARY_EXPRESSION, /**< scanning post primary expression */ + SCAN_MODE_PRIMARY_EXPRESSION_END, /**< scanning primary expression end */ + SCAN_MODE_STATEMENT, /**< scanning statement */ + SCAN_MODE_STATEMENT_OR_TERMINATOR, /**< scanning statement or statement end */ + SCAN_MODE_STATEMENT_END, /**< scanning statement end */ + SCAN_MODE_VAR_STATEMENT, /**< scanning var statement */ + SCAN_MODE_PROPERTY_NAME, /**< scanning property name */ + SCAN_MODE_FUNCTION_ARGUMENTS, /**< scanning function arguments */ + SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS, /**< continue scanning function arguments */ + SCAN_MODE_BINDING, /**< array or object binding */ + SCAN_MODE_CLASS_DECLARATION, /**< scanning class declaration */ + SCAN_MODE_CLASS_BODY, /**< scanning class body */ + SCAN_MODE_CLASS_BODY_NO_SCAN, /**< scanning class body without calling lexer_scan_identifier */ +} scan_modes_t; + +/** + * Scan stack mode types. + */ +typedef enum +{ + SCAN_STACK_SCRIPT, /**< script */ + SCAN_STACK_SCRIPT_FUNCTION, /**< script is a function body */ + SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */ + SCAN_STACK_FUNCTION_STATEMENT, /**< function statement */ + SCAN_STACK_FUNCTION_EXPRESSION, /**< function expression */ + SCAN_STACK_FUNCTION_PROPERTY, /**< function expression in an object literal */ + SCAN_STACK_FUNCTION_ARROW, /**< arrow function expression */ + SCAN_STACK_SWITCH_BLOCK, /**< block part of "switch" statement */ + SCAN_STACK_IF_STATEMENT, /**< statement part of "if" statements */ + SCAN_STACK_WITH_STATEMENT, /**< statement part of "with" statements */ + SCAN_STACK_WITH_EXPRESSION, /**< expression part of "with" statements */ + SCAN_STACK_DO_STATEMENT, /**< statement part of "do" statements */ + SCAN_STACK_DO_EXPRESSION, /**< expression part of "do" statements */ + SCAN_STACK_WHILE_EXPRESSION, /**< expression part of "while" iterator */ + SCAN_STACK_PAREN_EXPRESSION, /**< expression in brackets */ + SCAN_STACK_STATEMENT_WITH_EXPR, /**< statement which starts with expression enclosed in brackets */ + SCAN_STACK_BINDING_INIT, /**< post processing after a single initializer */ + SCAN_STACK_BINDING_LIST_INIT, /**< post processing after an initializer list */ + SCAN_STACK_LET, /**< let statement */ + SCAN_STACK_CONST, /**< const statement */ + /* The SCANNER_IS_FOR_START macro needs to be updated when the following constants are reordered. */ + SCAN_STACK_VAR, /**< var statement */ + SCAN_STACK_FOR_VAR_START, /**< start of "for" iterator with var statement */ + SCAN_STACK_FOR_LET_START, /**< start of "for" iterator with let statement */ + SCAN_STACK_FOR_CONST_START, /**< start of "for" iterator with const statement */ + SCAN_STACK_FOR_START, /**< start of "for" iterator */ + SCAN_STACK_FOR_CONDITION, /**< condition part of "for" iterator */ + SCAN_STACK_FOR_EXPRESSION, /**< expression part of "for" iterator */ + SCAN_STACK_SWITCH_EXPRESSION, /**< expression part of "switch" statement */ + SCAN_STACK_CASE_STATEMENT, /**< case statement inside a switch statement */ + SCAN_STACK_COLON_EXPRESSION, /**< expression between a question mark and colon */ + SCAN_STACK_TRY_STATEMENT, /**< try statement */ + SCAN_STACK_CATCH_STATEMENT, /**< catch statement */ + SCAN_STACK_ARRAY_LITERAL, /**< array literal or destructuring assignment or binding */ + SCAN_STACK_OBJECT_LITERAL, /**< object literal group */ + SCAN_STACK_PROPERTY_ACCESSOR, /**< property accessor in square brackets */ + /* These four must be in this order. */ + SCAN_STACK_COMPUTED_PROPERTY, /**< computed property name */ + SCAN_STACK_COMPUTED_GENERATOR, /**< computed generator function */ + SCAN_STACK_COMPUTED_ASYNC, /**< computed async function */ + SCAN_STACK_COMPUTED_ASYNC_GENERATOR, /**< computed async function */ + SCAN_STACK_TEMPLATE_STRING, /**< template string */ + SCAN_STACK_TAGGED_TEMPLATE_LITERAL, /**< tagged template literal */ + SCAN_STACK_PRIVATE_BLOCK_EARLY, /**< private block for single statements (force early declarations) */ + SCAN_STACK_PRIVATE_BLOCK, /**< private block for single statements */ + SCAN_STACK_ARROW_ARGUMENTS, /**< might be arguments of an arrow function */ + SCAN_STACK_ARROW_EXPRESSION, /**< expression body of an arrow function */ + SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR, /**< explicit class constructor */ + SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR, /**< implicit class constructor */ + SCAN_STACK_CLASS_STATEMENT, /**< class statement */ + SCAN_STACK_CLASS_EXPRESSION, /**< class expression */ + SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */ + SCAN_STACK_CLASS_FIELD_INITIALIZER, /**< class field initializer */ + SCAN_STACK_FUNCTION_PARAMETERS, /**< function parameter initializer */ + SCAN_STACK_FOR_START_PATTERN, /**< possible assignment pattern for "for" iterator */ + SCAN_STACK_USE_ASYNC, /**< an "async" identifier is used */ + SCAN_STACK_CLASS_STATIC_BLOCK, /**< class static block */ +#if JERRY_MODULE_SYSTEM + SCAN_STACK_EXPORT_DEFAULT, /**< scan primary expression after export default */ +#endif /* JERRY_MODULE_SYSTEM */ +} scan_stack_modes_t; + +/** + * Scanner context flag types. + */ +typedef enum +{ + SCANNER_CONTEXT_NO_FLAGS = 0, /**< no flags are set */ + SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION = (1 << 0), /**< throw async function error */ +} scanner_context_flags_t; + +/** + * Checks whether the stack top is a for statement start. + */ +#define SCANNER_IS_FOR_START(stack_top) ((stack_top) >= SCAN_STACK_FOR_VAR_START && (stack_top) <= SCAN_STACK_FOR_START) + +/** + * Generic descriptor which stores only the start position. + */ +typedef struct +{ + const uint8_t *source_p; /**< start source byte */ +} scanner_source_start_t; + +/** + * Descriptor for storing a binding literal on stack. + */ +typedef struct +{ + lexer_lit_location_t *literal_p; /**< binding literal */ +} scanner_binding_literal_t; + +/** + * Flags for type member of lexer_lit_location_t structure in the literal pool. + */ +typedef enum +{ + SCANNER_LITERAL_IS_ARG = (1 << 0), /**< literal is argument */ + SCANNER_LITERAL_IS_VAR = (1 << 1), /**< literal is var */ + /** literal is a destructured argument binding of a possible arrow function */ + SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG = SCANNER_LITERAL_IS_VAR, + SCANNER_LITERAL_IS_FUNC = (1 << 2), /**< literal is function */ + SCANNER_LITERAL_NO_REG = (1 << 3), /**< literal cannot be stored in a register */ + SCANNER_LITERAL_IS_LET = (1 << 4), /**< literal is let */ + /** literal is a function declared in this block (prevents declaring let/const with the same name) */ + SCANNER_LITERAL_IS_FUNC_DECLARATION = SCANNER_LITERAL_IS_LET, + SCANNER_LITERAL_IS_CONST = (1 << 5), /**< literal is const */ + /** literal is a destructured argument binding */ + SCANNER_LITERAL_IS_DESTRUCTURED_ARG = SCANNER_LITERAL_IS_CONST, + SCANNER_LITERAL_IS_USED = (1 << 6), /**< literal is used */ + SCANNER_LITERAL_EARLY_CREATE = (1 << 7), /**< binding should be created early with ECMA_VALUE_UNINITIALIZED */ +} scanner_literal_type_flags_t; + +/* + * Known combinations: + * + * SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION : + * function declared in this block + * SCANNER_LITERAL_IS_LOCAL : + * module import on global scope, catch block variable otherwise + * SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC : + * a function argument which is reassigned to a function later + * SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG : + * destructured binding argument + * SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_FUNC : + * destructured binding argument which is reassigned to a function later + */ + +/** + * Literal is a local declration (let, const, catch variable, etc.) + */ +#define SCANNER_LITERAL_IS_LOCAL (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST) + +/** + * Literal is a local function declaration + */ +#define SCANNER_LITERAL_IS_LOCAL_FUNC (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION) + +/** + * For statement descriptor. + */ +typedef struct +{ + /** shared fields of for statements */ + union + { + const uint8_t *source_p; /**< start source byte */ + scanner_for_info_t *for_info_p; /**< for info */ + } u; +} scanner_for_statement_t; + +/** + * Switch statement descriptor. + */ +typedef struct +{ + scanner_case_info_t **last_case_p; /**< last case info */ +} scanner_switch_statement_t; + +/** + * Types of scanner destructuring bindings. + */ +typedef enum +{ + /* Update SCANNER_NEEDS_BINDING_LIST after changing these values. */ + SCANNER_BINDING_NONE, /**< not a destructuring binding expression */ + SCANNER_BINDING_VAR, /**< destructuring var binding */ + SCANNER_BINDING_LET, /**< destructuring let binding */ + SCANNER_BINDING_CATCH, /**< destructuring catch binding */ + SCANNER_BINDING_CONST, /**< destructuring const binding */ + SCANNER_BINDING_ARG, /**< destructuring arg binding */ + SCANNER_BINDING_ARROW_ARG, /**< possible destructuring arg binding of an arrow function */ +} scanner_binding_type_t; + +/** + * Check whether a binding list is needed for the binding pattern. + */ +#define SCANNER_NEEDS_BINDING_LIST(type) ((type) >= SCANNER_BINDING_LET) + +/** + * Scanner binding items for destructuring binding patterns. + */ +typedef struct scanner_binding_item_t +{ + struct scanner_binding_item_t *next_p; /**< next binding in the list */ + lexer_lit_location_t *literal_p; /**< binding literal */ +} scanner_binding_item_t; + +/** + * Scanner binding lists for destructuring binding patterns. + */ +typedef struct scanner_binding_list_t +{ + struct scanner_binding_list_t *prev_p; /**< prev list */ + scanner_binding_item_t *items_p; /**< list of bindings */ + bool is_nested; /**< is nested binding declaration */ +} scanner_binding_list_t; + +/** + * Flags for scanner_literal_pool_t structure. + */ +typedef enum +{ + SCANNER_LITERAL_POOL_FUNCTION = (1 << 0), /**< literal pool represents a function */ + SCANNER_LITERAL_POOL_CLASS_NAME = (1 << 1), /**< literal pool which contains a class name */ + SCANNER_LITERAL_POOL_CLASS_FIELD = (1 << 2), /**< literal pool is created for a class field initializer */ + SCANNER_LITERAL_POOL_IS_STRICT = (1 << 3), /**< literal pool represents a strict mode code block */ + SCANNER_LITERAL_POOL_CAN_EVAL = (1 << 4), /**< prepare for executing eval in this block */ + SCANNER_LITERAL_POOL_NO_ARGUMENTS = (1 << 5), /**< arguments object must not be constructed, + * or arguments cannot be stored in registers if + * SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS is set */ + SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS = (1 << 6), /**< arguments is referenced in function args */ + SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT = (1 << 7), /**< function has complex (ES2015+) argument definition */ + SCANNER_LITERAL_POOL_IN_WITH = (1 << 8), /**< literal pool is in a with statement */ + SCANNER_LITERAL_POOL_ARROW = (1 << 9), /**< arrow function */ + SCANNER_LITERAL_POOL_GENERATOR = (1 << 10), /**< generator function */ + SCANNER_LITERAL_POOL_ASYNC = (1 << 11), /**< async function */ + SCANNER_LITERAL_POOL_FUNCTION_STATEMENT = (1 << 12), /**< function statement */ + SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE = (1 << 13), /**< function body contains super reference */ +#if JERRY_MODULE_SYSTEM + SCANNER_LITERAL_POOL_IN_EXPORT = (1 << 14), /**< the declared variables are exported by the module system */ +#endif /* JERRY_MODULE_SYSTEM */ +} scanner_literal_pool_flags_t; + +/** + * Define a function where no arguments are allowed. + */ +#define SCANNER_LITERAL_POOL_ARROW_FLAGS \ + (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_NO_ARGUMENTS | SCANNER_LITERAL_POOL_ARROW) + +/** + * This flag represents that the bracketed expression might be an async arrow function. + * The SCANNER_LITERAL_POOL_ARROW flag is reused for this purpose. + */ +#define SCANNER_LITERAL_POOL_MAY_ASYNC_ARROW SCANNER_LITERAL_POOL_ARROW + +/** + * Getting the generator and async properties of literal pool status flags. + */ +#define SCANNER_FROM_LITERAL_POOL_TO_COMPUTED(status_flags) \ + ((uint8_t) ((((status_flags) >> 10) & 0x3) + SCAN_STACK_COMPUTED_PROPERTY)) + +/** + * Setting the generator and async properties of literal pool status flags. + */ +#define SCANNER_FROM_COMPUTED_TO_LITERAL_POOL(mode) (((mode) -SCAN_STACK_COMPUTED_PROPERTY) << 10) + +/** + * Literal pool which may contains function argument identifiers + */ +#define SCANNER_LITERAL_POOL_MAY_HAVE_ARGUMENTS(status_flags) \ + (!((status_flags) & (SCANNER_LITERAL_POOL_CLASS_NAME | SCANNER_LITERAL_POOL_CLASS_FIELD))) + +/** + * Local literal pool. + */ +typedef struct scanner_literal_pool_t +{ + struct scanner_literal_pool_t *prev_p; /**< previous literal pool */ + const uint8_t *source_p; /**< source position where the final data needs to be inserted */ + parser_list_t literal_pool; /**< list of literal */ + uint16_t status_flags; /**< combination of scanner_literal_pool_flags_t flags */ + uint16_t no_declarations; /**< size of scope stack required during parsing */ +} scanner_literal_pool_t; + +/** + * Scanner context. + */ +struct scanner_context_t +{ + uint32_t context_status_flags; /**< original status flags of the context */ + uint8_t mode; /**< scanner mode */ + uint8_t binding_type; /**< current destructuring binding type */ + uint16_t status_flags; /**< scanner status flags */ + scanner_binding_list_t *active_binding_list_p; /**< currently active binding list */ + scanner_literal_pool_t *active_literal_pool_p; /**< currently active literal pool */ + scanner_switch_statement_t active_switch_statement; /**< currently active switch statement */ + scanner_info_t *end_arguments_p; /**< position of end arguments */ + const uint8_t *async_source_p; /**< source position for async functions */ +}; + +/* Scanner utils. */ + +void scanner_raise_error (parser_context_t *context_p); +void scanner_raise_redeclaration_error (parser_context_t *context_p); + +void *scanner_malloc (parser_context_t *context_p, size_t size); +void scanner_free (void *ptr, size_t size); + +size_t scanner_get_stream_size (scanner_info_t *info_p, size_t size); +scanner_info_t *scanner_insert_info (parser_context_t *context_p, const uint8_t *source_p, size_t size); +scanner_info_t *scanner_insert_info_before (parser_context_t *context_p, + const uint8_t *source_p, + scanner_info_t *start_info_p, + size_t size); +scanner_literal_pool_t * +scanner_push_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p, uint16_t status_flags); +void scanner_pop_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_filter_arguments (parser_context_t *context_p, scanner_context_t *scanner_context_p); +lexer_lit_location_t *scanner_add_custom_literal (parser_context_t *context_p, + scanner_literal_pool_t *literal_pool_p, + const lexer_lit_location_t *literal_location_p); +lexer_lit_location_t *scanner_add_literal (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_add_reference (parser_context_t *context_p, scanner_context_t *scanner_context_p); +lexer_lit_location_t *scanner_append_argument (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_add_private_identifier (parser_context_t *context_p, scanner_private_field_flags_t opts); +void scanner_detect_invalid_var (parser_context_t *context_p, + scanner_context_t *scanner_context_p, + lexer_lit_location_t *var_literal_p); +void scanner_detect_invalid_let (parser_context_t *context_p, lexer_lit_location_t *let_literal_p); +void scanner_detect_eval_call (parser_context_t *context_p, scanner_context_t *scanner_context_p); + +lexer_lit_location_t * +scanner_push_class_declaration (parser_context_t *context_p, scanner_context_t *scanner_context_p, uint8_t stack_mode); +void scanner_push_class_field_initializer (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_push_destructuring_pattern (parser_context_t *context_p, + scanner_context_t *scanner_context_p, + uint8_t binding_type, + bool is_nested); +void scanner_pop_binding_list (scanner_context_t *scanner_context_p); +void scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p); + +/* Scanner operations. */ + +void scanner_add_async_literal (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_check_arrow (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void +scanner_scan_simple_arrow (parser_context_t *context_p, scanner_context_t *scanner_context_p, const uint8_t *source_p); +void scanner_check_arrow_arg (parser_context_t *context_p, scanner_context_t *scanner_context_p); +bool scanner_check_async_function (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_check_function_after_if (parser_context_t *context_p, scanner_context_t *scanner_context_p); +#if JERRY_MODULE_SYSTEM +void scanner_check_import_meta (parser_context_t *context_p); +#endif /* JERRY_MODULE_SYSTEM */ +void scanner_scan_bracket (parser_context_t *context_p, scanner_context_t *scanner_context_p); +void scanner_check_directives (parser_context_t *context_p, scanner_context_t *scanner_context_p); + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_SCANNER_INTERNAL_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-ops.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-ops.cpp new file mode 100644 index 00000000..98dadc0f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-ops.cpp @@ -0,0 +1,602 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js-parser-internal.h" +#include "js-scanner-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Add the "async" literal to the literal pool. + */ +void +scanner_add_async_literal (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_lit_location_t async_literal; + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC); + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &async_literal, sizeof (lexer_lit_location_t)); + + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &async_literal); + + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } +} /* scanner_add_async_literal */ + +/** + * Init scanning the body of an arrow function. + */ +static void +scanner_check_arrow_body (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_next_token (context_p); + + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARROW; + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_EXPRESSION); + return; + } + + lexer_next_token (context_p); + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_ARROW); + scanner_check_directives (context_p, scanner_context_p); +} /* scanner_check_arrow_body */ + +/** + * Process arrow function with argument list. + */ +void +scanner_check_arrow (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + parser_stack_pop_uint8 (context_p); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_ARROW || (context_p->token.flags & LEXER_WAS_NEWLINE)) + { + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + scanner_pop_literal_pool (context_p, scanner_context_p); + return; + } + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + parser_stack_pop (context_p, NULL, sizeof (lexer_lit_location_t) + 1); + } + + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + uint16_t status_flags = literal_pool_p->status_flags; + + bool is_async_arrow = (status_flags & SCANNER_LITERAL_POOL_MAY_ASYNC_ARROW) != 0; + + status_flags |= SCANNER_LITERAL_POOL_ARROW_FLAGS; + status_flags &= + (uint16_t) ~(SCANNER_LITERAL_POOL_IN_WITH | SCANNER_LITERAL_POOL_GENERATOR | SCANNER_LITERAL_POOL_ASYNC); + + context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); + + if (is_async_arrow) + { + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + + literal_pool_p->status_flags = status_flags; + + scanner_filter_arguments (context_p, scanner_context_p); + scanner_check_arrow_body (context_p, scanner_context_p); +} /* scanner_check_arrow */ + +/** + * Process arrow function with a single argument. + */ +void +scanner_scan_simple_arrow (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + const uint8_t *source_p) /**< identifier end position */ +{ + uint16_t status_flags = SCANNER_LITERAL_POOL_ARROW_FLAGS; + + context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); + + if (scanner_context_p->async_source_p != NULL) + { + JERRY_ASSERT (scanner_context_p->async_source_p == source_p); + + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + + scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + literal_pool_p->source_p = source_p; + + lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p); + location_p->type |= SCANNER_LITERAL_IS_ARG; + + /* Skip the => token, which size is two. */ + context_p->source_p += 2; + PARSER_PLUS_EQUAL_LC (context_p->column, 2); + context_p->token.flags = (uint8_t) (context_p->token.flags & ~LEXER_NO_SKIP_SPACES); + + scanner_check_arrow_body (context_p, scanner_context_p); +} /* scanner_scan_simple_arrow */ + +/** + * Process the next argument of a might-be arrow function. + */ +void +scanner_check_arrow_arg (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS); + + const uint8_t *source_p = context_p->source_p; + bool process_arrow = false; + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (context_p->token.type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + } + + switch (context_p->token.type) + { + case LEXER_RIGHT_PAREN: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return; + } + case LEXER_LITERAL: + { + if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (lexer_check_arrow (context_p)) + { + process_arrow = true; + break; + } + + lexer_lit_location_t *argument_literal_p = scanner_append_argument (context_p, scanner_context_p); + + scanner_detect_eval_call (context_p, scanner_context_p); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_PAREN) + { + return; + } + + if (context_p->token.type != LEXER_ASSIGN) + { + break; + } + + if (argument_literal_p->type & SCANNER_LITERAL_IS_USED) + { + JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE); + return; + } + + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = argument_literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + return; + } + case LEXER_LEFT_SQUARE: + case LEXER_LEFT_BRACE: + { + scanner_append_hole (context_p, scanner_context_p); + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context_p->mode = SCAN_MODE_BINDING; + lexer_next_token (context_p); + return; + } + } + + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); + + if (process_arrow) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, source_p); + } +} /* scanner_check_arrow_arg */ + +/** + * Detect async functions. + * + * @return true, if async is followed by a function keyword, false otherwise + */ +bool +scanner_check_async_function (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + JERRY_ASSERT (lexer_token_is_async (context_p)); + JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION + || scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW); + JERRY_ASSERT (scanner_context_p->async_source_p != NULL); + + lexer_lit_location_t async_literal = context_p->token.lit_location; + + lexer_next_token (context_p); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + if (context_p->token.type == LEXER_KEYW_FUNCTION) + { + return true; + } + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + if (!lexer_check_arrow (context_p)) + { + scanner_raise_error (context_p); + } + + scanner_scan_simple_arrow (context_p, scanner_context_p, scanner_context_p->async_source_p); + scanner_context_p->async_source_p = NULL; + return false; + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + parser_stack_push (context_p, &async_literal, sizeof (lexer_lit_location_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_USE_ASYNC); + return false; + } + } + + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &async_literal); + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } + + scanner_context_p->async_source_p = NULL; + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return false; +} /* scanner_check_async_function */ + +/** + * Check whether the statement of an if/else construct is a function statement. + */ +void +scanner_check_function_after_if (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_next_token (context_p); + scanner_context_p->mode = SCAN_MODE_STATEMENT; + + if (JERRY_UNLIKELY (context_p->token.type == LEXER_KEYW_FUNCTION)) + { + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + + literal_pool_p->source_p = context_p->source_p; + parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK); + } +} /* scanner_check_function_after_if */ + +#if JERRY_MODULE_SYSTEM + +/** + * Check whether the next token is meta. + */ +void +scanner_check_import_meta (parser_context_t *context_p) /**< context */ +{ + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL + || context_p->token.keyword_type != LEXER_KEYW_META + || (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_IMPORT_META; +} /* scanner_check_import_meta */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Arrow types for scanner_scan_bracket() function. + */ +typedef enum +{ + SCANNER_SCAN_BRACKET_NO_ARROW, /**< not an arrow function */ + SCANNER_SCAN_BRACKET_SIMPLE_ARROW, /**< simple arrow function */ + SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG, /**< arrow function with one argument */ +} scanner_scan_bracket_arrow_type_t; + +/** + * Scan bracketed expressions. + */ +void +scanner_scan_bracket (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + size_t depth = 0; + const uint8_t *arrow_source_p; + const uint8_t *async_source_p = NULL; + scanner_scan_bracket_arrow_type_t arrow_type = SCANNER_SCAN_BRACKET_NO_ARROW; + + JERRY_ASSERT (context_p->token.type == LEXER_LEFT_PAREN); + + do + { + arrow_source_p = context_p->source_p; + depth++; + lexer_next_token (context_p); + } while (context_p->token.type == LEXER_LEFT_PAREN); + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + switch (context_p->token.type) + { + case LEXER_LITERAL: + { + if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + arrow_source_p = NULL; + break; + } + + const uint8_t *source_p = context_p->source_p; + + if (lexer_check_arrow (context_p)) + { + arrow_source_p = source_p; + arrow_type = SCANNER_SCAN_BRACKET_SIMPLE_ARROW; + break; + } + + size_t total_depth = depth; + + while (depth > 0 && lexer_check_next_character (context_p, LIT_CHAR_RIGHT_PAREN)) + { + lexer_consume_next_character (context_p); + depth--; + } + + if (context_p->token.keyword_type == LEXER_KEYW_EVAL + && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + /* A function call cannot be an eval function. */ + arrow_source_p = NULL; + const uint16_t flags = (uint16_t) (SCANNER_LITERAL_POOL_CAN_EVAL | SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE); + + scanner_context_p->active_literal_pool_p->status_flags |= flags; + break; + } + + if (total_depth == depth) + { + if (lexer_check_arrow_param (context_p)) + { + JERRY_ASSERT (depth > 0); + depth--; + break; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p))) + { + async_source_p = source_p; + } + } + + if (depth == total_depth - 1 && lexer_check_arrow (context_p)) + { + arrow_type = SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG; + break; + } + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + arrow_source_p = NULL; + break; + } + case LEXER_THREE_DOTS: + case LEXER_LEFT_SQUARE: + case LEXER_LEFT_BRACE: + case LEXER_RIGHT_PAREN: + { + JERRY_ASSERT (depth > 0); + depth--; + break; + } + default: + { + arrow_source_p = NULL; + break; + } + } + + if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL) && (arrow_source_p == NULL || depth > 0)) + { + scanner_context_p->async_source_p = NULL; + } + + while (depth > 0) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); + depth--; + } + + if (arrow_source_p != NULL) + { + JERRY_ASSERT (async_source_p == NULL); + + if (arrow_type == SCANNER_SCAN_BRACKET_SIMPLE_ARROW) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, arrow_source_p); + return; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_ARGUMENTS); + + uint16_t status_flags = 0; + + if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL)) + { + status_flags |= SCANNER_LITERAL_POOL_MAY_ASYNC_ARROW; + arrow_source_p = scanner_context_p->async_source_p; + scanner_context_p->async_source_p = NULL; + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + literal_pool_p->source_p = arrow_source_p; + + if (arrow_type == SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG) + { + scanner_append_argument (context_p, scanner_context_p); + scanner_detect_eval_call (context_p, scanner_context_p); + + context_p->token.type = LEXER_RIGHT_PAREN; + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + else if (context_p->token.type == LEXER_RIGHT_PAREN) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + else + { + scanner_check_arrow_arg (context_p, scanner_context_p); + } + } + else if (JERRY_UNLIKELY (async_source_p != NULL)) + { + scanner_context_p->async_source_p = async_source_p; + scanner_check_async_function (context_p, scanner_context_p); + } +} /* scanner_scan_bracket */ + +/** + * Check directives before a source block. + */ +void +scanner_check_directives (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + + while (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + bool is_use_strict = false; + + if (lexer_string_is_use_strict (context_p) && !(context_p->status_flags & PARSER_IS_STRICT)) + { + is_use_strict = true; + context_p->status_flags |= PARSER_IS_STRICT; + } + + lexer_next_token (context_p); + + if (!lexer_string_is_directive (context_p)) + { + if (is_use_strict) + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + + /* The string is part of an expression statement. */ + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + break; + } + + if (is_use_strict) + { + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IS_STRICT; + } + + if (context_p->token.type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + } + } +} /* scanner_check_directives */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-util.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-util.cpp new file mode 100644 index 00000000..a9c9655a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner-util.cpp @@ -0,0 +1,2950 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers.h" +#include "ecma-lex-env.h" + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "js-scanner-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +JERRY_STATIC_ASSERT (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS < PARSER_REGISTER_START, + maximum_number_of_literals_plus_registers_must_be_less_than_register_start); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) == 0, + is_arrow_arg_binding_flag_must_not_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_LET & SCANNER_LITERAL_IS_LOCAL) != 0, is_let_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_CONST & SCANNER_LITERAL_IS_LOCAL) != 0, is_const_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_FUNC_DECLARATION & SCANNER_LITERAL_IS_LOCAL) != 0, + is_func_declaration_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) != 0, + is_arg_binding_flag_must_use_local_flags); + +JERRY_STATIC_ASSERT (((int)SCANNER_LITERAL_IS_FUNC_DECLARATION != (int)SCANNER_LITERAL_IS_DESTRUCTURED_ARG), + is_func_declaration_must_be_different_from_is_arg_binding); + +JERRY_STATIC_ASSERT (((int)PARSER_SCOPE_STACK_IS_CONST_REG == (int)PARSER_SCOPE_STACK_IS_LOCAL_CREATED), + scope_stack_is_const_reg_and_scope_stack_is_local_created_must_be_the_same); + +/** + * Raise a scanner error. + */ +void +scanner_raise_error (parser_context_t *context_p /**< context */) +{ + PARSER_THROW (context_p->try_buffer); + /* Should never been reached. */ + JERRY_ASSERT (0); +} /* scanner_raise_error */ + +/** + * Raise a variable redeclaration error. + */ +void +scanner_raise_redeclaration_error (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_ERR_REDECLARED; + + scanner_raise_error (context_p); +} /* scanner_raise_redeclaration_error */ + +/** + * Allocate memory for scanner. + * + * @return allocated memory + */ +void * +scanner_malloc (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + void *result; + + JERRY_ASSERT (size > 0); + result = jmem_heap_alloc_block_null_on_error (size); + + if (result == NULL) + { + scanner_cleanup (context_p); + + /* This is the only error which specify its reason. */ + context_p->error = PARSER_ERR_OUT_OF_MEMORY; + PARSER_THROW (context_p->try_buffer); + } + return result; +} /* scanner_malloc */ + +/** + * Free memory allocated by scanner_malloc. + */ +void +scanner_free (void *ptr, /**< pointer to free */ + size_t size) /**< size of the memory block */ +{ + jmem_heap_free_block (ptr, size); +} /* scanner_free */ + +/** + * Count the size of a stream after an info block. + * + * @return the size in bytes + */ +size_t +scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */ + size_t size) /**< size excluding the stream */ +{ + const uint8_t *data_p = ((const uint8_t *) info_p) + size; + const uint8_t *data_p_start = data_p; + + while (data_p[0] != SCANNER_STREAM_TYPE_END) + { + switch (data_p[0] & SCANNER_STREAM_TYPE_MASK) + { + case SCANNER_STREAM_TYPE_VAR: + case SCANNER_STREAM_TYPE_LET: + case SCANNER_STREAM_TYPE_CONST: + case SCANNER_STREAM_TYPE_LOCAL: +#if JERRY_MODULE_SYSTEM + case SCANNER_STREAM_TYPE_IMPORT: +#endif /* JERRY_MODULE_SYSTEM */ + case SCANNER_STREAM_TYPE_ARG: + case SCANNER_STREAM_TYPE_ARG_VAR: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + case SCANNER_STREAM_TYPE_ARG_FUNC: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + case SCANNER_STREAM_TYPE_FUNC: + { + break; + } + default: + { + JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE + || SCANNER_STREAM_TYPE_IS_ARGUMENTS (data_p[0] & SCANNER_STREAM_TYPE_MASK)); + data_p++; + continue; + } + } + + data_p += 3; + + if (data_p[-3] & SCANNER_STREAM_UINT16_DIFF) + { + data_p++; + } + else if (data_p[-1] == 0) + { + data_p += sizeof (const uint8_t *); + } + } + + return size + 1 + (size_t) (data_p - data_p_start); +} /* scanner_get_stream_size */ + +/** + * Insert a scanner info block into the scanner info chain. + * + * @return newly allocated scanner info + */ +scanner_info_t * +scanner_insert_info (parser_context_t *context_p, /**< context */ + const uint8_t *source_p, /**< triggering position */ + size_t size) /**< size of the memory block */ +{ + scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size); + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + scanner_info_t *prev_scanner_info_p = NULL; + + JERRY_ASSERT (scanner_info_p != NULL); + JERRY_ASSERT (source_p != NULL); + + new_scanner_info_p->source_p = source_p; + + while (source_p < scanner_info_p->source_p) + { + prev_scanner_info_p = scanner_info_p; + scanner_info_p = scanner_info_p->next_p; + + JERRY_ASSERT (scanner_info_p != NULL); + } + + /* Multiple scanner info blocks cannot be assigned to the same position. */ + JERRY_ASSERT (source_p != scanner_info_p->source_p); + + new_scanner_info_p->next_p = scanner_info_p; + + if (JERRY_LIKELY (prev_scanner_info_p == NULL)) + { + context_p->next_scanner_info_p = new_scanner_info_p; + } + else + { + prev_scanner_info_p->next_p = new_scanner_info_p; + } + + return new_scanner_info_p; +} /* scanner_insert_info */ + +/** + * Insert a scanner info block into the scanner info chain before a given info block. + * + * @return newly allocated scanner info + */ +scanner_info_t * +scanner_insert_info_before (parser_context_t *context_p, /**< context */ + const uint8_t *source_p, /**< triggering position */ + scanner_info_t *start_info_p, /**< first info position */ + size_t size) /**< size of the memory block */ +{ + JERRY_ASSERT (start_info_p != NULL); + + scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size); + scanner_info_t *scanner_info_p = start_info_p->next_p; + scanner_info_t *prev_scanner_info_p = start_info_p; + + new_scanner_info_p->source_p = source_p; + + while (source_p < scanner_info_p->source_p) + { + prev_scanner_info_p = scanner_info_p; + scanner_info_p = scanner_info_p->next_p; + + JERRY_ASSERT (scanner_info_p != NULL); + } + + /* Multiple scanner info blocks cannot be assigned to the same position. */ + JERRY_ASSERT (source_p != scanner_info_p->source_p); + + new_scanner_info_p->next_p = scanner_info_p; + + prev_scanner_info_p->next_p = new_scanner_info_p; + return new_scanner_info_p; +} /* scanner_insert_info_before */ + +/** + * Release the next scanner info. + */ +void +scanner_release_next (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + scanner_info_t *next_p = context_p->next_scanner_info_p->next_p; + + jmem_heap_free_block (context_p->next_scanner_info_p, size); + context_p->next_scanner_info_p = next_p; +} /* scanner_release_next */ + +/** + * Set the active scanner info to the next scanner info. + */ +void +scanner_set_active (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + + context_p->next_scanner_info_p = scanner_info_p->next_p; + scanner_info_p->next_p = context_p->active_scanner_info_p; + context_p->active_scanner_info_p = scanner_info_p; +} /* scanner_set_active */ + +/** + * Set the next scanner info to the active scanner info. + */ +void +scanner_revert_active (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *scanner_info_p = context_p->active_scanner_info_p; + + context_p->active_scanner_info_p = scanner_info_p->next_p; + scanner_info_p->next_p = context_p->next_scanner_info_p; + context_p->next_scanner_info_p = scanner_info_p; +} /* scanner_revert_active */ + +/** + * Release the active scanner info. + */ +void +scanner_release_active (parser_context_t *context_p, /**< context */ + size_t size) /**< size of the memory block */ +{ + scanner_info_t *next_p = context_p->active_scanner_info_p->next_p; + + jmem_heap_free_block (context_p->active_scanner_info_p, size); + context_p->active_scanner_info_p = next_p; +} /* scanner_release_active */ + +/** + * Release switch cases. + */ +void +scanner_release_switch_cases (scanner_case_info_t *case_p) /**< case list */ +{ + while (case_p != NULL) + { + scanner_case_info_t *next_p = case_p->next_p; + + jmem_heap_free_block (case_p, sizeof (scanner_case_info_t)); + case_p = next_p; + } +} /* scanner_release_switch_cases */ + +/** + * Release private fields. + */ +void +scanner_release_private_fields (scanner_class_private_member_t *member_p) /**< private member list */ +{ + while (member_p != NULL) + { + scanner_class_private_member_t *prev_p = member_p->prev_p; + + jmem_heap_free_block (member_p, sizeof (scanner_class_private_member_t)); + member_p = prev_p; + } +} /* scanner_release_private_fields */ + +/** + * Seek to correct position in the scanner info list. + */ +void +scanner_seek (parser_context_t *context_p) /**< context */ +{ + const uint8_t *source_p = context_p->source_p; + scanner_info_t *prev_p; + + if (context_p->skipped_scanner_info_p != NULL) + { + JERRY_ASSERT (context_p->skipped_scanner_info_p->source_p != NULL); + + context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p; + + if (context_p->skipped_scanner_info_end_p->source_p <= source_p) + { + prev_p = context_p->skipped_scanner_info_end_p; + } + else + { + prev_p = context_p->skipped_scanner_info_p; + + if (prev_p->source_p > source_p) + { + context_p->next_scanner_info_p = prev_p; + context_p->skipped_scanner_info_p = NULL; + return; + } + + context_p->skipped_scanner_info_p = prev_p; + } + } + else + { + prev_p = context_p->next_scanner_info_p; + + if (prev_p->source_p == NULL || prev_p->source_p > source_p) + { + return; + } + + context_p->skipped_scanner_info_p = prev_p; + } + + while (prev_p->next_p->source_p != NULL && prev_p->next_p->source_p <= source_p) + { + prev_p = prev_p->next_p; + } + + context_p->skipped_scanner_info_end_p = prev_p; + context_p->next_scanner_info_p = prev_p->next_p; +} /* scanner_seek */ + +/** + * Checks whether a literal is equal to "arguments". + */ +static inline bool +scanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */ +{ + return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9); +} /* scanner_literal_is_arguments */ + +/** + * Find if there is a duplicated argument in the given context + * + * @return true - if there are duplicates, false - otherwise + */ +static bool +scanner_find_duplicated_arg (parser_context_t *context_p, lexer_lit_location_t *lit_loc_p) +{ + if (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)) + { + return false; + } + + if (scanner_literal_is_arguments (lit_loc_p)) + { + return true; + } + + uint16_t register_end, encoding_limit, encoding_delta; + ecma_value_t *literal_p; + ecma_value_t *literal_start_p; + + const ecma_compiled_code_t *bytecode_header_p = JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + uint8_t *byte_code_p = (uint8_t *) literal_p; + + bool found_duplicate = false; + + while (*byte_code_p == CBC_CREATE_LOCAL) + { + byte_code_p++; + uint16_t literal_index = *byte_code_p++; + + if (literal_index >= encoding_limit) + { + literal_index = (uint16_t) (((literal_index << 8) | *byte_code_p++) - encoding_delta); + } + + ecma_string_t *arg_string = ecma_get_string_from_value (literal_start_p[literal_index]); + uint8_t *destination_p = (uint8_t *) parser_malloc (context_p, lit_loc_p->length); + lexer_convert_ident_to_cesu8 (destination_p, lit_loc_p->char_p, lit_loc_p->length); + ecma_string_t *search_key_p = ecma_new_ecma_string_from_utf8 (destination_p, lit_loc_p->length); + scanner_free (destination_p, lit_loc_p->length); + + found_duplicate = ecma_compare_ecma_strings (arg_string, search_key_p); + ecma_deref_ecma_string (search_key_p); + + if (found_duplicate) + { + break; + } + } + + return found_duplicate; +} /* scanner_find_duplicated_arg */ + +/** + * Find any let/const declaration of a given literal. + * + * @return true - if the literal is found, false - otherwise + */ +static bool +scanner_scope_find_lexical_declaration (parser_context_t *context_p, /**< context */ + lexer_lit_location_t *literal_p) /**< literal */ +{ + ecma_string_t *name_p; + uint32_t flags = context_p->global_status_flags; + + if (!(flags & ECMA_PARSE_EVAL) || (!(flags & ECMA_PARSE_DIRECT_EVAL) && (context_p->status_flags & PARSER_IS_STRICT))) + { + return false; + } + + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + name_p = ecma_new_ecma_string_from_utf8 (literal_p->char_p, literal_p->length); + } + else + { + uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length); + + lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length); + + name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length); + + scanner_free (destination_p, literal_p->length); + } + + ecma_object_t *lex_env_p; + + if (flags & ECMA_PARSE_DIRECT_EVAL) + { + lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL && ecma_is_property_enumerable (*property_p)) + { + ecma_deref_ecma_string (name_p); + return true; + } + } + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + } + else + { + lex_env_p = ecma_get_global_scope (ecma_builtin_get_global ()); + } + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL + && (ecma_is_property_enumerable (*property_p) || scanner_find_duplicated_arg (context_p, literal_p))) + { + ecma_deref_ecma_string (name_p); + return true; + } + } + + ecma_deref_ecma_string (name_p); + return false; +} /* scanner_scope_find_lexical_declaration */ + +/** + * Push a new literal pool. + * + * @return the newly created literal pool + */ +scanner_literal_pool_t * +scanner_push_literal_pool (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + uint16_t status_flags) /**< combination of scanner_literal_pool_flags_t flags */ +{ + scanner_literal_pool_t *prev_literal_pool_p = scanner_context_p->active_literal_pool_p; + scanner_literal_pool_t *literal_pool_p; + + literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t)); + + if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + { + JERRY_ASSERT (prev_literal_pool_p != NULL); + status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS; + + const uint16_t copied_flags = + (SCANNER_LITERAL_POOL_IN_WITH | SCANNER_LITERAL_POOL_GENERATOR | SCANNER_LITERAL_POOL_ASYNC); + + status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags); + } + else + { + context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION); + + if (status_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + + if (status_flags & SCANNER_LITERAL_POOL_ASYNC) + { + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + } + + if (prev_literal_pool_p != NULL) + { + const uint16_t copied_flags = SCANNER_LITERAL_POOL_IS_STRICT; + status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags); + + /* The logical value of these flags must be the same. */ + JERRY_ASSERT (!(status_flags & SCANNER_LITERAL_POOL_IS_STRICT) == !(context_p->status_flags & PARSER_IS_STRICT)); + } + + parser_list_init (&literal_pool_p->literal_pool, + sizeof (lexer_lit_location_t), + (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t))); + literal_pool_p->source_p = NULL; + literal_pool_p->status_flags = status_flags; + literal_pool_p->no_declarations = 0; + + literal_pool_p->prev_p = prev_literal_pool_p; + scanner_context_p->active_literal_pool_p = literal_pool_p; + + return literal_pool_p; +} /* scanner_push_literal_pool */ + +JERRY_STATIC_ASSERT (((uint8_t)PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX), maximum_ident_length_must_fit_in_a_byte); + +/** + * Current status of arguments. + */ +typedef enum +{ + SCANNER_ARGUMENTS_NOT_PRESENT, /**< arguments object must not be created */ + SCANNER_ARGUMENTS_MAY_PRESENT, /**< arguments object can be created */ + SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL, /**< arguments object must be present unless otherwise declared */ + SCANNER_ARGUMENTS_PRESENT, /**< arguments object must be created */ + SCANNER_ARGUMENTS_PRESENT_NO_REG, /**< arguments object must be created and cannot be stored in registers */ +} scanner_arguments_type_t; + +/** + * Pop the last literal pool from the end. + */ +void +scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p; + + const uint32_t arrow_super_flags = (SCANNER_LITERAL_POOL_ARROW | SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE); + if ((literal_pool_p->status_flags & arrow_super_flags) == arrow_super_flags) + { + prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE; + } + + if (JERRY_UNLIKELY (literal_pool_p->source_p == NULL)) + { + JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION); + JERRY_ASSERT (literal_pool_p->literal_pool.data.first_p == NULL + && literal_pool_p->literal_pool.data.last_p == NULL); + + scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p; + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); + return; + } + + uint16_t status_flags = literal_pool_p->status_flags; + scanner_arguments_type_t arguments_type = SCANNER_ARGUMENTS_MAY_PRESENT; + + if (status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) + { + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + } + else if (status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL; + } + + if (status_flags & SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT; + + if (status_flags & (SCANNER_LITERAL_POOL_NO_ARGUMENTS | SCANNER_LITERAL_POOL_CAN_EVAL)) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_NO_ARGUMENTS; + } + } + + uint8_t can_eval_types = 0; + + if (prev_literal_pool_p == NULL && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)) + { + can_eval_types |= SCANNER_LITERAL_IS_FUNC; + } + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && prev_literal_pool_p != NULL) + { + prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL; + } + + parser_list_iterator_t literal_iterator; + lexer_lit_location_t *literal_p; + int32_t no_declarations = literal_pool_p->no_declarations; + + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + uint8_t arguments_stream_type = SCANNER_STREAM_TYPE_ARGUMENTS; + const uint8_t *prev_source_p = literal_pool_p->source_p - 1; + lexer_lit_location_t *last_argument_p = NULL; + size_t compressed_size = 1; + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + uint8_t type = literal_p->type; + + if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)) + { + continue; + } + + if (!(status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) && scanner_literal_is_arguments (literal_p)) + { + JERRY_ASSERT (arguments_type != SCANNER_ARGUMENTS_NOT_PRESENT); + status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS; + + if (type & SCANNER_LITERAL_IS_ARG) + { + JERRY_ASSERT (arguments_type != SCANNER_ARGUMENTS_PRESENT + && arguments_type != SCANNER_ARGUMENTS_PRESENT_NO_REG); + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + last_argument_p = literal_p; + } + else if (type & SCANNER_LITERAL_IS_LOCAL) + { + if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT || arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + } + else + { + if (arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG) + { + type |= SCANNER_LITERAL_NO_REG; + } + else if (type & (SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE)) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + + if ((type & SCANNER_LITERAL_IS_LOCAL_FUNC) == SCANNER_LITERAL_IS_LOCAL_FUNC) + { + type |= SCANNER_LITERAL_IS_ARG; + literal_p->type = type; + no_declarations--; + arguments_stream_type = SCANNER_STREAM_TYPE_ARGUMENTS_FUNC; + } + else + { + arguments_stream_type |= SCANNER_STREAM_LOCAL_ARGUMENTS; + } + } + } + else + { + if ((type & SCANNER_LITERAL_IS_VAR) + && (arguments_type == SCANNER_ARGUMENTS_PRESENT || arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG)) + { + if (arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG) + { + type |= SCANNER_LITERAL_NO_REG; + } + else if (type & (SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE)) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + + type |= SCANNER_LITERAL_IS_ARG; + literal_p->type = type; + no_declarations--; + } + + if ((type & SCANNER_LITERAL_NO_REG) || arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + else if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT; + } + + /* The SCANNER_LITERAL_IS_ARG may be set above. */ + if (!(type & SCANNER_LITERAL_IS_ARG)) + { + literal_p->type = 0; + continue; + } + } + } + else if (type & SCANNER_LITERAL_IS_ARG) + { + last_argument_p = literal_p; + } + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && (type & SCANNER_LITERAL_IS_LOCAL_FUNC) == SCANNER_LITERAL_IS_FUNC) + { + if (prev_literal_pool_p == NULL && scanner_scope_find_lexical_declaration (context_p, literal_p)) + { + literal_p->type = 0; + continue; + } + + if (!(type & SCANNER_LITERAL_IS_ARG)) + { + type |= SCANNER_LITERAL_IS_VAR; + } + + type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC; + literal_p->type = type; + } + + if ((type & SCANNER_LITERAL_IS_LOCAL) + || ((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) + && (status_flags & SCANNER_LITERAL_POOL_FUNCTION))) + { + JERRY_ASSERT ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || !(literal_p->type & SCANNER_LITERAL_IS_ARG)); + + if (literal_p->length == 0) + { + compressed_size += 1; + continue; + } + + no_declarations++; + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) || (type & can_eval_types)) + { + type |= SCANNER_LITERAL_NO_REG; + literal_p->type = type; + } + + if (type & SCANNER_LITERAL_IS_FUNC) + { + no_declarations++; + + if ((type & (SCANNER_LITERAL_IS_CONST | SCANNER_LITERAL_IS_ARG)) == SCANNER_LITERAL_IS_CONST) + { + JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET); + + /* Catch parameters cannot be functions. */ + literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC); + no_declarations--; + } + } + + intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p); + + if (diff >= 1 && diff <= (intptr_t) UINT8_MAX) + { + compressed_size += 2 + 1; + } + else if (diff >= -(intptr_t) UINT8_MAX && diff <= (intptr_t) UINT16_MAX) + { + compressed_size += 2 + 2; + } + else + { + compressed_size += 2 + 1 + sizeof (const uint8_t *); + } + + prev_source_p = literal_p->char_p + literal_p->length; + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) + || ((type & SCANNER_LITERAL_IS_FUNC) && (status_flags & SCANNER_LITERAL_POOL_IS_STRICT)) + || !(type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC))) + { + continue; + } + } + + if (prev_literal_pool_p != NULL && literal_p->length > 0) + { + /* Propagate literal to upper level. */ + lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p, prev_literal_pool_p, literal_p); + uint8_t extended_type = literal_location_p->type; + + if ((status_flags & (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_CLASS_FIELD)) + || (type & SCANNER_LITERAL_NO_REG)) + { + extended_type |= SCANNER_LITERAL_NO_REG; + } + + extended_type |= SCANNER_LITERAL_IS_USED; + + if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT) + { + extended_type |= SCANNER_LITERAL_EARLY_CREATE; + } + + const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_LOCAL); + + if ((type & SCANNER_LITERAL_IS_ARG) || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_LET + || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_CONST) + { + /* Clears the SCANNER_LITERAL_IS_VAR and SCANNER_LITERAL_IS_FUNC flags + * for speculative arrow parameters and local (non-var) functions. */ + type = 0; + } + + type = (uint8_t) (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC)); + JERRY_ASSERT (type == 0 || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION)); + + literal_location_p->type = (uint8_t) (extended_type | type); + } + } + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (compressed_size > 1)) + { + if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT) + { + arguments_type = SCANNER_ARGUMENTS_NOT_PRESENT; + } + else if (arguments_type == SCANNER_ARGUMENTS_MAY_PRESENT_IN_EVAL) + { + arguments_type = SCANNER_ARGUMENTS_PRESENT_NO_REG; + } + + if (arguments_type != SCANNER_ARGUMENTS_NOT_PRESENT) + { + compressed_size++; + } + + compressed_size += sizeof (scanner_info_t); + + scanner_info_t *info_p; + + if (prev_literal_pool_p != NULL || scanner_context_p->end_arguments_p == NULL) + { + info_p = scanner_insert_info (context_p, literal_pool_p->source_p, compressed_size); + } + else + { + scanner_info_t *start_info_p = scanner_context_p->end_arguments_p; + info_p = scanner_insert_info_before (context_p, literal_pool_p->source_p, start_info_p, compressed_size); + } + + if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK) + { + no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK; + } + + uint8_t *data_p = (uint8_t *) (info_p + 1); + bool mapped_arguments = false; + + if (status_flags & SCANNER_LITERAL_POOL_FUNCTION) + { + info_p->type = SCANNER_TYPE_FUNCTION; + + uint8_t u8_arg = 0; + + if (arguments_type != SCANNER_ARGUMENTS_NOT_PRESENT) + { + u8_arg |= SCANNER_FUNCTION_ARGUMENTS_NEEDED; + + if (no_declarations < PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK) + { + no_declarations++; + } + + if (!(status_flags & (SCANNER_LITERAL_POOL_IS_STRICT | SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT))) + { + mapped_arguments = true; + } + + if (arguments_type == SCANNER_ARGUMENTS_PRESENT_NO_REG) + { + arguments_stream_type |= SCANNER_STREAM_NO_REG; + } + + if (last_argument_p == NULL) + { + *data_p++ = arguments_stream_type; + } + } + else + { + last_argument_p = NULL; + } + + if (status_flags & (SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT | SCANNER_LITERAL_POOL_ARROW)) + { + u8_arg |= SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT; + } + + if (status_flags & SCANNER_LITERAL_POOL_ASYNC) + { + u8_arg |= SCANNER_FUNCTION_ASYNC; + + if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT) + { + u8_arg |= SCANNER_FUNCTION_STATEMENT; + } + } + + if (status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) + { + u8_arg |= SCANNER_FUNCTION_LEXICAL_ENV_NEEDED; + } + + if (status_flags & SCANNER_LITERAL_POOL_IS_STRICT) + { + u8_arg |= SCANNER_FUNCTION_IS_STRICT; + } + + info_p->u8_arg = u8_arg; + info_p->u16_arg = (uint16_t) no_declarations; + } + else + { + info_p->type = SCANNER_TYPE_BLOCK; + + JERRY_ASSERT (prev_literal_pool_p != NULL); + } + + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + prev_source_p = literal_pool_p->source_p - 1; + no_declarations = literal_pool_p->no_declarations; + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK) + || (!(literal_p->type & SCANNER_LITERAL_IS_LOCAL) + && (!(literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) + || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION)))) + { + continue; + } + + if (literal_p->length == 0) + { + *data_p++ = SCANNER_STREAM_TYPE_HOLE; + + if (literal_p == last_argument_p) + { + *data_p++ = arguments_stream_type; + } + continue; + } + + no_declarations++; + + uint8_t type = SCANNER_STREAM_TYPE_VAR; + + if (literal_p->type & SCANNER_LITERAL_IS_FUNC) + { + no_declarations++; + type = SCANNER_STREAM_TYPE_FUNC; + + if (literal_p->type & SCANNER_LITERAL_IS_ARG) + { + type = SCANNER_STREAM_TYPE_ARG_FUNC; + + if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + { + type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC; + } + } + } + else if (literal_p->type & SCANNER_LITERAL_IS_ARG) + { + type = SCANNER_STREAM_TYPE_ARG; + + if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + { + type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG; + } + + if (literal_p->type & SCANNER_LITERAL_IS_VAR) + { + type = (uint8_t) (type + 1); + + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR); + } + } + else if (literal_p->type & SCANNER_LITERAL_IS_LET) + { + if (!(literal_p->type & SCANNER_LITERAL_IS_CONST)) + { + type = SCANNER_STREAM_TYPE_LET; + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG)) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + } +#if JERRY_MODULE_SYSTEM + else if (prev_literal_pool_p == NULL) + { + type = SCANNER_STREAM_TYPE_IMPORT; + } +#endif /* JERRY_MODULE_SYSTEM */ + else + { + type = SCANNER_STREAM_TYPE_LOCAL; + } + } + else if (literal_p->type & SCANNER_LITERAL_IS_CONST) + { + type = SCANNER_STREAM_TYPE_CONST; + + if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG)) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + } + + if (literal_p->type & SCANNER_LITERAL_EARLY_CREATE) + { + type |= SCANNER_STREAM_NO_REG | SCANNER_STREAM_EARLY_CREATE; + } + + if (literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE) + { + type |= SCANNER_STREAM_HAS_ESCAPE; + } + + if ((literal_p->type & SCANNER_LITERAL_NO_REG) + || (mapped_arguments && (literal_p->type & SCANNER_LITERAL_IS_ARG))) + { + type |= SCANNER_STREAM_NO_REG; + } + + data_p[0] = type; + data_p[1] = (uint8_t) literal_p->length; + data_p += 3; + + intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p); + + if (diff >= 1 && diff <= (intptr_t) UINT8_MAX) + { + data_p[-1] = (uint8_t) diff; + } + else if (diff >= -(intptr_t) UINT8_MAX && diff <= (intptr_t) UINT16_MAX) + { + if (diff < 0) + { + diff = -diff; + } + + data_p[-3] |= SCANNER_STREAM_UINT16_DIFF; + data_p[-1] = (uint8_t) diff; + data_p[0] = (uint8_t) (diff >> 8); + data_p += 1; + } + else + { + data_p[-1] = 0; + memcpy (data_p, &literal_p->char_p, sizeof (uintptr_t)); + data_p += sizeof (uintptr_t); + } + + if (literal_p == last_argument_p) + { + *data_p++ = arguments_stream_type; + } + + prev_source_p = literal_p->char_p + literal_p->length; + } + + data_p[0] = SCANNER_STREAM_TYPE_END; + + JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1); + } + + if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && (int32_t) prev_literal_pool_p->no_declarations < no_declarations) + { + prev_literal_pool_p->no_declarations = (uint16_t) no_declarations; + } + + if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) && prev_literal_pool_p != NULL) + { + if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IS_STRICT) + { + context_p->status_flags |= PARSER_IS_STRICT; + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT; + } + + if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION; + } + + if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_ASYNC) + { + context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION; + } + else + { + context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION; + } + } + + scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p; + + parser_list_free (&literal_pool_p->literal_pool); + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); +} /* scanner_pop_literal_pool */ + +/** + * Filter out the arguments from a literal pool. + */ +void +scanner_filter_arguments (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + /* Fast case: check whether all literals are arguments. */ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p; + parser_list_iterator_t literal_iterator; + lexer_lit_location_t *literal_p; + bool can_eval = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) != 0; + bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0; + + JERRY_ASSERT (SCANNER_LITERAL_POOL_MAY_HAVE_ARGUMENTS (literal_pool_p->status_flags)); + + if (JERRY_UNLIKELY (can_eval)) + { + if (prev_literal_pool_p != NULL) + { + prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL; + } + + literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_CAN_EVAL; + } + else + { + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + while (true) + { + literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator); + + if (literal_p == NULL) + { + return; + } + + if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE)) + { + literal_p->type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE; + } + + uint8_t type = literal_p->type; + const uint8_t mask = + (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG); + + if ((type & mask) != SCANNER_LITERAL_IS_ARG) + { + break; + } + } + } + + /* Destructured args are placed after the other arguments because of register assignments. */ + bool has_destructured_arg = false; + scanner_literal_pool_t *new_literal_pool_p; + + new_literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t)); + + new_literal_pool_p->prev_p = literal_pool_p; + scanner_context_p->active_literal_pool_p = new_literal_pool_p; + + *new_literal_pool_p = *literal_pool_p; + parser_list_init (&new_literal_pool_p->literal_pool, + sizeof (lexer_lit_location_t), + (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t))); + + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + uint8_t type = literal_p->type; + + if (type & SCANNER_LITERAL_IS_ARG) + { + if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE)) + { + type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE; + literal_p->type = type; + } + + if (has_arguments && scanner_literal_is_arguments (literal_p)) + { + has_arguments = false; + } + + if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG)) + { + has_destructured_arg = true; + + if (type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + { + continue; + } + + type &= (uint8_t) ~SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG; + type |= SCANNER_LITERAL_IS_DESTRUCTURED_ARG; + + literal_p->type = type; + continue; + } + + lexer_lit_location_t *new_literal_p; + new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool); + *new_literal_p = *literal_p; + } + else if (has_arguments && scanner_literal_is_arguments (literal_p)) + { + /* Arguments object is directly referenced from the function arguments */ + new_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS; + + if (type & SCANNER_LITERAL_NO_REG) + { + new_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS; + } + } + else if (prev_literal_pool_p != NULL) + { + /* Propagate literal to upper level. */ + lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p, prev_literal_pool_p, literal_p); + type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_IS_USED; + literal_location_p->type |= type; + } + } + + if (has_destructured_arg) + { + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + const uint8_t expected_flags = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG; + + if ((literal_p->type & expected_flags) == expected_flags) + { + lexer_lit_location_t *new_literal_p; + new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool); + *new_literal_p = *literal_p; + } + } + } + + if (has_arguments) + { + /* Force the lexically stored arguments object creation */ + new_literal_pool_p->status_flags |= (SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS | SCANNER_LITERAL_POOL_NO_ARGUMENTS); + } + + new_literal_pool_p->prev_p = prev_literal_pool_p; + + parser_list_free (&literal_pool_p->literal_pool); + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); +} /* scanner_filter_arguments */ + +/** + * Add any literal to the specified literal pool. + * + * @return pointer to the literal + */ +lexer_lit_location_t * +scanner_add_custom_literal (parser_context_t *context_p, /**< context */ + scanner_literal_pool_t *literal_pool_p, /**< literal pool */ + const lexer_lit_location_t *literal_location_p) /**< literal */ +{ + while (true) + { + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + lexer_lit_location_t *literal_p; + + const uint8_t *char_p = literal_location_p->char_p; + prop_length_t length = literal_location_p->length; + + if (JERRY_LIKELY (!(literal_location_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->length == length) + { + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + if (memcmp (literal_p->char_p, char_p, length) == 0) + { + return literal_p; + } + } + else if (lexer_compare_identifier_to_string (literal_p, char_p, length)) + { + /* The non-escaped version is preferred. */ + literal_p->char_p = char_p; + literal_p->status_flags = LEXER_LIT_LOCATION_NO_OPTS; + return literal_p; + } + } + } + } + else + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (lexer_compare_identifiers (context_p, literal_p, literal_location_p)) + { + return literal_p; + } + } + } + + if (JERRY_UNLIKELY (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME)) + { + literal_pool_p = literal_pool_p->prev_p; + continue; + } + + literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool); + *literal_p = *literal_location_p; + + literal_p->type = 0; + + return literal_p; + } +} /* scanner_add_custom_literal */ + +/** + * Add the current literal token to the current literal pool. + * + * @return pointer to the literal + */ +lexer_lit_location_t * +scanner_add_literal (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + return scanner_add_custom_literal (context_p, + scanner_context_p->active_literal_pool_p, + &context_p->token.lit_location); +} /* scanner_add_literal */ + +/** + * Add the current literal token to the current literal pool and + * set SCANNER_LITERAL_NO_REG if it is inside a with statement. + * + * @return pointer to the literal + */ +void +scanner_add_reference (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &context_p->token.lit_location); + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } + + scanner_detect_eval_call (context_p, scanner_context_p); +} /* scanner_add_reference */ + +/** + * Append an argument to the literal pool. If the argument is already present, make it a "hole". + * + * @return newly created literal + */ +lexer_lit_location_t * +scanner_append_argument (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + lexer_lit_location_t *literal_location_p = &context_p->token.lit_location; + lexer_lit_location_t *literal_p; + + const uint8_t *char_p = literal_location_p->char_p; + prop_length_t length = literal_location_p->length; + + JERRY_ASSERT (SCANNER_LITERAL_POOL_MAY_HAVE_ARGUMENTS (literal_pool_p->status_flags)); + + if (JERRY_LIKELY (!(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (literal_p->length == length) + { + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + if (memcmp (literal_p->char_p, char_p, length) == 0) + { + break; + } + } + else if (lexer_compare_identifier_to_string (literal_p, char_p, length)) + { + break; + } + } + } + } + else + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if (lexer_compare_identifiers (context_p, literal_p, literal_location_p)) + { + break; + } + } + } + + uint8_t literal_type = SCANNER_LITERAL_IS_ARG; + + if (literal_p != NULL) + { + literal_p->length = 0; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_type = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_EARLY_CREATE; + } + } + + literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool); + + *literal_p = context_p->token.lit_location; + literal_p->type = literal_type; + + return literal_p; +} /* scanner_append_argument */ + +/** + * Add private identifiers to private ident pool + */ +void +scanner_add_private_identifier (parser_context_t *context_p, /**< context */ + scanner_private_field_flags_t opts) /**< options */ +{ + scan_stack_modes_t stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + scanner_class_info_t *class_info_p; + parser_stack_pop (context_p, &class_info_p, sizeof (scanner_class_info_t *)); + + scanner_class_private_member_t *iter = class_info_p->members; + + scanner_private_field_flags_t search_flag = + (((unsigned int) opts & (unsigned int) SCANNER_PRIVATE_FIELD_PROPERTY) ? SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER + : (scanner_private_field_flags_t) ((unsigned int) opts & (unsigned int) SCANNER_PRIVATE_FIELD_GETTER_SETTER)); + + while (iter != NULL) + { + if (lexer_compare_identifiers (context_p, &context_p->token.lit_location, &iter->loc) + && (iter->u8_arg & search_flag)) + { + scanner_raise_error (context_p); + } + + iter = iter->prev_p; + } + + scanner_class_private_member_t *p_member; + p_member = (scanner_class_private_member_t *) scanner_malloc (context_p, sizeof (scanner_class_private_member_t)); + p_member->loc = context_p->token.lit_location; + p_member->u8_arg = (uint8_t) opts; + p_member->prev_p = class_info_p->members; + class_info_p->members = p_member; + + parser_stack_push (context_p, &class_info_p, sizeof (scanner_class_info_t *)); + parser_stack_push_uint8 (context_p, (uint8_t) stack_top); +} /* scanner_add_private_identifier */ + +/** + * Check whether an eval call is performed and update the status flags accordingly. + */ +void +scanner_detect_eval_call (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /**< scanner context */ +{ + if (context_p->token.keyword_type == LEXER_KEYW_EVAL && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + scanner_context_p->active_literal_pool_p->status_flags |= + (SCANNER_LITERAL_POOL_CAN_EVAL | SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE); + } +} /* scanner_detect_eval_call */ + +/** + * Throws an error for invalid var statements. + */ +void +scanner_detect_invalid_var (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_lit_location_t *var_literal_p) /**< var literal */ +{ + if (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL + && !(var_literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG)) + && (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL) + { + scanner_raise_redeclaration_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + if (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && ((var_literal_p->type & SCANNER_LITERAL_IS_LOCAL_FUNC) == SCANNER_LITERAL_IS_LOCAL_FUNC)) + { + scanner_raise_redeclaration_error (context_p); + } + + const uint8_t *char_p = var_literal_p->char_p; + prop_length_t length = var_literal_p->length; + + while (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + { + literal_pool_p = literal_pool_p->prev_p; + + parser_list_iterator_t literal_iterator; + parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator); + lexer_lit_location_t *literal_p; + + if (JERRY_LIKELY (!(context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL) && !(literal_p->type & SCANNER_LITERAL_IS_ARG) + && !((literal_p->type & SCANNER_LITERAL_IS_FUNC) + && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL && literal_p->length == length) + { + if (JERRY_LIKELY (!(literal_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))) + { + if (memcmp (literal_p->char_p, char_p, length) == 0) + { + scanner_raise_redeclaration_error (context_p); + return; + } + } + else if (lexer_compare_identifier_to_string (literal_p, char_p, length)) + { + scanner_raise_redeclaration_error (context_p); + return; + } + } + } + } + else + { + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL) && !(literal_p->type & SCANNER_LITERAL_IS_ARG) + && !((literal_p->type & SCANNER_LITERAL_IS_FUNC) + && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)) + && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL + && lexer_compare_identifiers (context_p, literal_p, var_literal_p)) + { + scanner_raise_redeclaration_error (context_p); + return; + } + } + } + } + + if (scanner_scope_find_lexical_declaration (context_p, var_literal_p)) + { + scanner_raise_redeclaration_error (context_p); + } +} /* scanner_detect_invalid_var */ + +/** + * Throws an error for invalid let statements. + */ +void +scanner_detect_invalid_let (parser_context_t *context_p, /**< context */ + lexer_lit_location_t *let_literal_p) /**< let literal */ +{ + if (let_literal_p->type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_LOCAL)) + { + scanner_raise_redeclaration_error (context_p); + } + + if (let_literal_p->type & SCANNER_LITERAL_IS_FUNC) + { + let_literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC; + } +} /* scanner_detect_invalid_let */ + +/** + * Push the values required for class declaration parsing. + * + * @return literal reference created for class statements, NULL otherwise + */ +lexer_lit_location_t * +scanner_push_class_declaration (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /* scanner context */ + uint8_t stack_mode) /**< stack mode */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS); + + const uint8_t *source_p = context_p->source_p; + lexer_lit_location_t *literal_p = NULL; + +#if JERRY_MODULE_SYSTEM + bool is_export_default = context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT; + JERRY_ASSERT (!is_export_default || stack_mode == SCAN_STACK_CLASS_EXPRESSION); +#endif /* JERRY_MODULE_SYSTEM */ + + parser_stack_push_uint8 (context_p, stack_mode); + lexer_next_token (context_p); + + bool class_has_name = + (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (class_has_name) + { + literal_p = scanner_add_literal (context_p, scanner_context_p); + scanner_context_p->active_literal_pool_p->no_declarations++; + +#if JERRY_MODULE_SYSTEM + if (is_export_default) + { + scanner_detect_invalid_let (context_p, literal_p); + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + + literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG; + } +#endif /* JERRY_MODULE_SYSTEM */ + } + + scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + + if (class_has_name) + { + scanner_add_literal (context_p, scanner_context_p); + scanner_context_p->active_literal_pool_p->no_declarations++; + } +#if JERRY_MODULE_SYSTEM + else if (is_export_default) + { + lexer_lit_location_t *name_literal_p; + name_literal_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p->prev_p, &lexer_default_literal); + + name_literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG; + scanner_context_p->active_literal_pool_p->no_declarations++; + } +#endif /* JERRY_MODULE_SYSTEM */ + + literal_pool_p->source_p = source_p; + literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CLASS_NAME; + + const uint8_t *class_source_p = scanner_context_p->active_literal_pool_p->source_p; + scanner_class_info_t *class_info_p = + (scanner_class_info_t *) scanner_insert_info (context_p, class_source_p, sizeof (scanner_class_info_t)); + + class_info_p->info.type = SCANNER_TYPE_CLASS_CONSTRUCTOR; + class_info_p->members = NULL; + class_info_p->info.u8_arg = SCANNER_CONSTRUCTOR_IMPLICIT; + + parser_stack_push (context_p, &class_info_p, sizeof (scanner_class_info_t *)); + parser_stack_push_uint8 (context_p, SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR); + scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION; + + return literal_p; +} /* scanner_push_class_declaration */ + +/** + * Push the start of a class field initializer. + */ +void +scanner_push_class_field_initializer (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /* scanner context */ +{ + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_FIELD_INITIALIZER); + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_CLASS_FIELD); + literal_pool_p->source_p = context_p->source_p; + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; +} /* scanner_push_class_field_initializer */ + +/** + * Push the values required for destructuring assignment or binding parsing. + */ +void +scanner_push_destructuring_pattern (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + uint8_t binding_type, /**< type of destructuring binding pattern */ + bool is_nested) /**< nested declaration */ +{ + JERRY_ASSERT (binding_type != SCANNER_BINDING_NONE || !is_nested); + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, scanner_context_p->binding_type); + scanner_context_p->binding_type = binding_type; + + if (SCANNER_NEEDS_BINDING_LIST (binding_type)) + { + scanner_binding_list_t *binding_list_p; + binding_list_p = (scanner_binding_list_t *) scanner_malloc (context_p, sizeof (scanner_binding_list_t)); + + binding_list_p->prev_p = scanner_context_p->active_binding_list_p; + binding_list_p->items_p = NULL; + binding_list_p->is_nested = is_nested; + + scanner_context_p->active_binding_list_p = binding_list_p; + } +} /* scanner_push_destructuring_pattern */ + +/** + * Pop binding list. + */ +void +scanner_pop_binding_list (scanner_context_t *scanner_context_p) /**< scanner context */ +{ + scanner_binding_list_t *binding_list_p = scanner_context_p->active_binding_list_p; + JERRY_ASSERT (binding_list_p != NULL); + + scanner_binding_item_t *item_p = binding_list_p->items_p; + scanner_binding_list_t *prev_binding_list_p = binding_list_p->prev_p; + bool is_nested = binding_list_p->is_nested; + + scanner_free (binding_list_p, sizeof (scanner_binding_list_t)); + scanner_context_p->active_binding_list_p = prev_binding_list_p; + + if (!is_nested) + { + while (item_p != NULL) + { + scanner_binding_item_t *next_p = item_p->next_p; + + JERRY_ASSERT (item_p->literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_ARG)); + + scanner_free (item_p, sizeof (scanner_binding_item_t)); + item_p = next_p; + } + return; + } + + JERRY_ASSERT (prev_binding_list_p != NULL); + + while (item_p != NULL) + { + scanner_binding_item_t *next_p = item_p->next_p; + + item_p->next_p = prev_binding_list_p->items_p; + prev_binding_list_p->items_p = item_p; + + item_p = next_p; + } +} /* scanner_pop_binding_list */ + +/** + * Append a hole into the literal pool. + */ +void +scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p) +{ + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + lexer_lit_location_t *literal_p; + literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool); + + literal_p->char_p = NULL; + literal_p->length = 0; + literal_p->type = SCANNER_LITERAL_IS_ARG; + literal_p->status_flags = LEXER_LIT_LOCATION_NO_OPTS; +} /* scanner_append_hole */ + +/** + * Reverse the scanner info chain after the scanning is completed. + */ +void +scanner_reverse_info_list (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + scanner_info_t *last_scanner_info_p = NULL; + + if (scanner_info_p->type == SCANNER_TYPE_END) + { + return; + } + + do + { + scanner_info_t *next_scanner_info_p = scanner_info_p->next_p; + scanner_info_p->next_p = last_scanner_info_p; + + last_scanner_info_p = scanner_info_p; + scanner_info_p = next_scanner_info_p; + } while (scanner_info_p->type != SCANNER_TYPE_END); + + context_p->next_scanner_info_p->next_p = scanner_info_p; + context_p->next_scanner_info_p = last_scanner_info_p; +} /* scanner_reverse_info_list */ + +/** + * Release unused scanner info blocks. + * This should happen only if an error is occurred. + */ +void +scanner_cleanup (parser_context_t *context_p) /**< context */ +{ + if (context_p->skipped_scanner_info_p != NULL) + { + context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p; + context_p->next_scanner_info_p = context_p->skipped_scanner_info_p; + context_p->skipped_scanner_info_p = NULL; + } + + scanner_info_t *scanner_info_p = context_p->next_scanner_info_p; + + while (scanner_info_p != NULL) + { + scanner_info_t *next_scanner_info_p = scanner_info_p->next_p; + + size_t size = sizeof (scanner_info_t); + + switch (scanner_info_p->type) + { + case SCANNER_TYPE_END: + { + scanner_info_p = context_p->active_scanner_info_p; + continue; + } + case SCANNER_TYPE_FUNCTION: + case SCANNER_TYPE_BLOCK: + { + size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t)); + break; + } + case SCANNER_TYPE_WHILE: + case SCANNER_TYPE_FOR_IN: + case SCANNER_TYPE_FOR_OF: + case SCANNER_TYPE_CASE: + case SCANNER_TYPE_INITIALIZER: + case SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END: + case SCANNER_TYPE_CLASS_STATIC_BLOCK_END: + { + size = sizeof (scanner_location_info_t); + break; + } + case SCANNER_TYPE_FOR: + { + size = sizeof (scanner_for_info_t); + break; + } + case SCANNER_TYPE_SWITCH: + { + scanner_release_switch_cases (((scanner_switch_info_t *) scanner_info_p)->case_p); + size = sizeof (scanner_switch_info_t); + break; + } + case SCANNER_TYPE_CLASS_CONSTRUCTOR: + { + scanner_release_private_fields (((scanner_class_info_t *) scanner_info_p)->members); + size = sizeof (scanner_class_info_t); + break; + } + default: + { + JERRY_ASSERT ( + scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS || scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS + || scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION || scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED + || scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION + || scanner_info_p->type == SCANNER_TYPE_EXPORT_MODULE_SPECIFIER); + break; + } + } + + scanner_free (scanner_info_p, size); + scanner_info_p = next_scanner_info_p; + } + + context_p->next_scanner_info_p = NULL; + context_p->active_scanner_info_p = NULL; +} /* scanner_cleanup */ + +/** + * Checks whether a context needs to be created for a block. + * + * @return true - if context is needed, + * false - otherwise + */ +bool +scanner_is_context_needed (parser_context_t *context_p, /**< context */ + parser_check_context_type_t check_type) /**< context type */ +{ + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *data_p = (const uint8_t *) (info_p + 1); + + JERRY_UNUSED (check_type); + + JERRY_ASSERT ((check_type == PARSER_CHECK_BLOCK_CONTEXT ? info_p->type == SCANNER_TYPE_BLOCK + : info_p->type == SCANNER_TYPE_FUNCTION)); + + uint32_t scope_stack_reg_top = + (check_type != PARSER_CHECK_GLOBAL_CONTEXT ? context_p->scope_stack_reg_top : 1); /* block result */ + + while (data_p[0] != SCANNER_STREAM_TYPE_END) + { + uint8_t data = data_p[0]; + uint32_t type = data & SCANNER_STREAM_TYPE_MASK; + + if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT)) + { + if (JERRY_UNLIKELY (type == SCANNER_STREAM_TYPE_HOLE)) + { + data_p++; + continue; + } + + if (JERRY_UNLIKELY (SCANNER_STREAM_TYPE_IS_ARGUMENTS (type))) + { + if ((data & SCANNER_STREAM_NO_REG) || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + return true; + } + + scope_stack_reg_top++; + data_p++; + continue; + } + } + +#ifndef JERRY_NDEBUG + if (check_type == PARSER_CHECK_BLOCK_CONTEXT) + { + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_LET + || type == SCANNER_STREAM_TYPE_CONST || type == SCANNER_STREAM_TYPE_LOCAL + || type == SCANNER_STREAM_TYPE_FUNC); + } + else if (check_type == PARSER_CHECK_GLOBAL_CONTEXT) + { +#if JERRY_MODULE_SYSTEM + const bool is_import = (type == SCANNER_STREAM_TYPE_IMPORT); +#else /* !JERRY_MODULE_SYSTEM */ + const bool is_import = true; +#endif /* JERRY_MODULE_SYSTEM */ + + /* FIXME: a private declarative lexical environment should always be present + * for modules. Remove SCANNER_STREAM_TYPE_IMPORT after it is implemented. */ + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_LET + || type == SCANNER_STREAM_TYPE_CONST || type == SCANNER_STREAM_TYPE_FUNC || is_import); + + /* Only let/const can be stored in registers */ + JERRY_ASSERT ((data & SCANNER_STREAM_NO_REG) + || (type == SCANNER_STREAM_TYPE_FUNC && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)) + || type == SCANNER_STREAM_TYPE_LET || type == SCANNER_STREAM_TYPE_CONST); + } + else + { + JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT); + + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_LET + || type == SCANNER_STREAM_TYPE_CONST || type == SCANNER_STREAM_TYPE_LOCAL + || type == SCANNER_STREAM_TYPE_ARG || type == SCANNER_STREAM_TYPE_ARG_VAR + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR + || type == SCANNER_STREAM_TYPE_ARG_FUNC || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC + || type == SCANNER_STREAM_TYPE_FUNC); + } +#endif /* !JERRY_NDEBUG */ + if (!(data & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + data_p += 2 + 1; + } + else + { + data_p += 2 + 1 + sizeof (const uint8_t *); + } + } + else + { + data_p += 2 + 2; + } + +#if JERRY_MODULE_SYSTEM + const bool is_import = (type == SCANNER_STREAM_TYPE_IMPORT); +#else /* !JERRY_MODULE_SYSTEM */ + const bool is_import = false; +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (check_type == PARSER_CHECK_GLOBAL_CONTEXT) + && (type == SCANNER_STREAM_TYPE_VAR + || (type == SCANNER_STREAM_TYPE_FUNC && !(context_p->global_status_flags & ECMA_PARSE_EVAL)) || is_import)) + { + continue; + } + + if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT)) + { + if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) || type == SCANNER_STREAM_TYPE_ARG_VAR + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR) + { + /* The return value is true, if the variable is stored in the lexical environment + * or all registers have already been used for function arguments. This can be + * inprecise in the latter case, but this is a very rare corner case. A more + * sophisticated check would require to decode the literal. */ + if ((data & SCANNER_STREAM_NO_REG) || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + return true; + } + continue; + } + + if (SCANNER_STREAM_TYPE_IS_ARG (type)) + { + continue; + } + } + + if ((data & SCANNER_STREAM_NO_REG) || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + return true; + } + + scope_stack_reg_top++; + } + + return false; +} /* scanner_is_context_needed */ + +/** + * Try to scan/parse the ".target" part in the "new.target" expression. + * + * Upon exiting with "true" the current token will point to the "target" + * literal. + * + * If the "target" literal is not after the "new." then a scanner/parser + * error will be raised. + * + * @returns true if the ".target" part was found + * false if there is no "." after the new. + */ +bool +scanner_try_scan_new_target (parser_context_t *context_p) /**< parser/scanner context */ +{ + JERRY_ASSERT (context_p->token.type == LEXER_KEYW_NEW); + + if (lexer_check_next_character (context_p, LIT_CHAR_DOT)) + { + lexer_next_token (context_p); + if (context_p->token.type != LEXER_DOT) + { + parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); + } + + lexer_next_token (context_p); + if (!lexer_token_is_identifier (context_p, "target", 6)) + { + parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_EXPECTED); + } + + return true; + } + return false; +} /* scanner_try_scan_new_target */ + +/** + * Description of "arguments" literal string. + */ +const lexer_lit_location_t lexer_arguments_literal = { (const uint8_t *) "arguments", + 9, + LEXER_IDENT_LITERAL, + LEXER_LIT_LOCATION_IS_ASCII }; + +/** + * Create an unused literal. + */ +static void +scanner_create_unused_literal (parser_context_t *context_p, /**< context */ + uint8_t status_flags) /**< initial status flags */ +{ + if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + + literal_p->type = LEXER_UNUSED_LITERAL; + literal_p->status_flags = status_flags; + + context_p->literal_count++; +} /* scanner_create_unused_literal */ + +/** + * Emit checks for redeclared bindings in the global lexical scope. + */ +void +scanner_check_variables (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *next_data_p = (const uint8_t *) (info_p + 1); + lexer_lit_location_t literal; + + JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION); + + literal.char_p = info_p->source_p - 1; + + while (next_data_p[0] != SCANNER_STREAM_TYPE_END) + { + uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK; + const uint8_t *data_p = next_data_p; + + JERRY_ASSERT (type != SCANNER_STREAM_TYPE_HOLE && !SCANNER_STREAM_TYPE_IS_ARG (type) + && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)); + JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG); + + if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + literal.char_p += data_p[2]; + next_data_p += 2 + 1; + } + else + { + memcpy (&literal.char_p, data_p + 2 + 1, sizeof (uintptr_t)); + next_data_p += 2 + 1 + sizeof (uintptr_t); + } + } + else + { + int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8; + + if (diff <= (intptr_t) UINT8_MAX) + { + diff = -diff; + } + + literal.char_p += diff; + next_data_p += 2 + 2; + } + + literal.length = data_p[1]; + literal.type = LEXER_IDENT_LITERAL; + literal.status_flags = + ((data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? LEXER_LIT_LOCATION_HAS_ESCAPE : LEXER_LIT_LOCATION_NO_OPTS); + + lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL); + literal.char_p += data_p[1]; + +#if JERRY_MODULE_SYSTEM + if (type == SCANNER_STREAM_TYPE_IMPORT) + { + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + + uint16_t opcode; + if (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_FUNC) + { + opcode = CBC_CHECK_VAR; + } + else + { + opcode = CBC_CHECK_LET; + } + + parser_emit_cbc_literal (context_p, opcode, context_p->lit_object.index); + } + + parser_flush_cbc (context_p); +} /* scanner_check_variables */ + +/** + * Create and/or initialize var/let/const/function/etc. variables. + */ +void +scanner_create_variables (parser_context_t *context_p, /**< context */ + uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */ +{ + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *next_data_p = (const uint8_t *) (info_p + 1); + uint8_t info_type = info_p->type; + uint8_t info_u8_arg = info_p->u8_arg; + lexer_lit_location_t literal; + parser_scope_stack_t *scope_stack_p; + parser_scope_stack_t *scope_stack_end_p; + + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK); + JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) + || !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)); + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION + || !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY))); + + uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top; + + if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)) + { + JERRY_ASSERT (context_p->scope_stack_p == NULL); + + size_t stack_size = info_p->u16_arg * sizeof (parser_scope_stack_t); + context_p->scope_stack_size = info_p->u16_arg; + + scope_stack_p = NULL; + + if (stack_size > 0) + { + scope_stack_p = (parser_scope_stack_t *) parser_malloc (context_p, stack_size); + } + + context_p->scope_stack_p = scope_stack_p; + scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; + + if (option_flags & (SCANNER_CREATE_VARS_IS_SCRIPT | SCANNER_CREATE_VARS_IS_MODULE)) + { + scope_stack_reg_top++; /* block result */ + } + } + else + { + JERRY_ASSERT (context_p->scope_stack_p != NULL || context_p->scope_stack_size == 0); + + scope_stack_p = context_p->scope_stack_p; + scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; + scope_stack_p += context_p->scope_stack_top; + } + + literal.char_p = info_p->source_p - 1; + + while (next_data_p[0] != SCANNER_STREAM_TYPE_END) + { + uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK; + const uint8_t *data_p = next_data_p; + + JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)) + || (type != SCANNER_STREAM_TYPE_HOLE && !SCANNER_STREAM_TYPE_IS_ARG (type) + && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))); + +#if JERRY_MODULE_SYSTEM + JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG)); +#endif /* JERRY_MODULE_SYSTEM */ + + if (JERRY_UNLIKELY (type == SCANNER_STREAM_TYPE_HOLE)) + { + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION); + next_data_p++; + + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + continue; + } + + uint8_t mask = SCANNER_FUNCTION_ARGUMENTS_NEEDED | SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT; + + if (!(context_p->status_flags & PARSER_IS_STRICT) && (info_u8_arg & mask) == SCANNER_FUNCTION_ARGUMENTS_NEEDED) + { + scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT); + } + + if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + scope_stack_reg_top++; + } + continue; + } + + if (JERRY_UNLIKELY (SCANNER_STREAM_TYPE_IS_ARGUMENTS (type))) + { + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION); + next_data_p++; + + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + continue; + } + + context_p->status_flags |= PARSER_ARGUMENTS_NEEDED; + + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + lexer_construct_literal_object (context_p, &lexer_arguments_literal, LEXER_NEW_IDENT_LITERAL); + scope_stack_p->map_from = context_p->lit_object.index; + + uint16_t map_to; + + if (!(data_p[0] & SCANNER_STREAM_NO_REG) && scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top); + + scope_stack_p->map_to = (uint16_t) (scope_stack_reg_top + 1); + scope_stack_reg_top++; + } + else + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + map_to = context_p->lit_object.index; + + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + + if (data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) + { + context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; + } + + scope_stack_p->map_to = 0; + } + + scope_stack_p++; + +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_emit_cbc_ext_literal (context_p, CBC_EXT_CREATE_ARGUMENTS, map_to); + + if (type == SCANNER_STREAM_TYPE_ARGUMENTS_FUNC) + { + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC; + scope_stack_p->map_to = context_p->literal_count; + scope_stack_p++; + + scanner_create_unused_literal (context_p, 0); + } + + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) + { + break; + } + continue; + } + + JERRY_ASSERT (context_p->scope_stack_size != 0); + + if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + literal.char_p += data_p[2]; + next_data_p += 2 + 1; + } + else + { + memcpy (&literal.char_p, data_p + 2 + 1, sizeof (uintptr_t)); + next_data_p += 2 + 1 + sizeof (uintptr_t); + } + } + else + { + int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8; + + if (diff <= (intptr_t) UINT8_MAX) + { + diff = -diff; + } + + literal.char_p += diff; + next_data_p += 2 + 2; + } + + if (SCANNER_STREAM_TYPE_IS_ARG (type)) + { + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + if ((context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + && (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR)) + { + literal.length = data_p[1]; + literal.type = LEXER_IDENT_LITERAL; + literal.status_flags = + ((data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? LEXER_LIT_LOCATION_HAS_ESCAPE : LEXER_LIT_LOCATION_NO_OPTS); + + /* Literal must be exists. */ + lexer_construct_literal_object (context_p, &literal, LEXER_IDENT_LITERAL); + + if (context_p->lit_object.index < PARSER_REGISTER_START) + { + parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_COPY_FROM_ARG); + } + } + + literal.char_p += data_p[1]; + continue; + } + } + else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)) + { + /* Function arguments must come first. */ + break; + } + + literal.length = data_p[1]; + literal.type = LEXER_IDENT_LITERAL; + literal.status_flags = + ((data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? LEXER_LIT_LOCATION_HAS_ESCAPE : LEXER_LIT_LOCATION_NO_OPTS); + + lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL); + literal.char_p += data_p[1]; + + if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)) + { + JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2); + JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION); + JERRY_ASSERT (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)); + + parser_scope_stack_t *function_map_p = scope_stack_p - 2; + uint16_t literal_index = context_p->lit_object.index; + + while (literal_index != function_map_p->map_from) + { + function_map_p--; + + JERRY_ASSERT (function_map_p >= context_p->scope_stack_p); + } + + JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC); + + cbc_opcode_t opcode = CBC_SET_VAR_FUNC; + + if (JERRY_UNLIKELY (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED) + && (function_map_p[0].map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0) + { + opcode = CBC_INIT_ARG_OR_FUNC; + } + + parser_emit_cbc_literal_value (context_p, + (uint16_t) opcode, + function_map_p[1].map_to, + scanner_decode_map_to (function_map_p)); + continue; + } + + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + + scope_stack_p->map_from = context_p->lit_object.index; + + if (info_type == SCANNER_TYPE_FUNCTION) + { + if (type != SCANNER_STREAM_TYPE_LET +#if JERRY_MODULE_SYSTEM + && type != SCANNER_STREAM_TYPE_IMPORT +#endif /* JERRY_MODULE_SYSTEM */ + && type != SCANNER_STREAM_TYPE_CONST) + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL; + } + } + + uint16_t map_to; + uint16_t func_init_opcode = CBC_INIT_ARG_OR_FUNC; + + if (!(data_p[0] & SCANNER_STREAM_NO_REG) && scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top); + scope_stack_p->map_to = (uint16_t) (scope_stack_reg_top + 1); + scope_stack_reg_top++; + + switch (type) + { + case SCANNER_STREAM_TYPE_CONST: + { + scope_stack_p->map_to |= PARSER_SCOPE_STACK_IS_CONST_REG; + /* FALLTHRU */ + } + case SCANNER_STREAM_TYPE_LET: + case SCANNER_STREAM_TYPE_ARG: + case SCANNER_STREAM_TYPE_ARG_VAR: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + case SCANNER_STREAM_TYPE_ARG_FUNC: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + { + scope_stack_p->map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY; + break; + } + } + + func_init_opcode = CBC_SET_VAR_FUNC; + } + else + { + context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED; + map_to = context_p->lit_object.index; + + uint16_t scope_stack_map_to = 0; + + if (info_type == SCANNER_TYPE_FUNCTION) + { + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; + } + + switch (type) + { + case SCANNER_STREAM_TYPE_LET: + case SCANNER_STREAM_TYPE_CONST: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + { + scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY; + + if (!(data_p[0] & SCANNER_STREAM_EARLY_CREATE)) + { + break; + } + scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED; + /* FALLTHRU */ + } + case SCANNER_STREAM_TYPE_LOCAL: + case SCANNER_STREAM_TYPE_VAR: + { +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + uint16_t opcode; + + switch (type) + { + case SCANNER_STREAM_TYPE_LET: + { + opcode = CBC_CREATE_LET; + break; + } + case SCANNER_STREAM_TYPE_CONST: + { + opcode = CBC_CREATE_CONST; + break; + } + case SCANNER_STREAM_TYPE_VAR: + { + opcode = CBC_CREATE_VAR; + + if (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) + { + opcode = CBC_CREATE_VAR_EVAL; + + if ((context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + && !(context_p->status_flags & PARSER_IS_STRICT)) + { + opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL); + } + } + break; + } + default: + { + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_LOCAL || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC); + + opcode = CBC_CREATE_LOCAL; + break; + } + } + + parser_emit_cbc_literal (context_p, opcode, map_to); + break; + } + case SCANNER_STREAM_TYPE_ARG: + case SCANNER_STREAM_TYPE_ARG_VAR: + case SCANNER_STREAM_TYPE_ARG_FUNC: + { +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY; + + /* Argument initializers of functions with simple arguments (e.g. function f(a,b,a) {}) are + * generated here. The other initializers are handled by parser_parse_function_arguments(). */ + if (!(info_u8_arg & SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT)) + { + parser_emit_cbc_literal_value (context_p, + CBC_INIT_ARG_OR_FUNC, + (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top), + map_to); + } + else if (data_p[0] & SCANNER_STREAM_EARLY_CREATE) + { + parser_emit_cbc_literal (context_p, CBC_CREATE_LOCAL, map_to); + scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED; + } + + if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) + { + scope_stack_reg_top++; + } + break; + } + } + + scope_stack_p->map_to = scope_stack_map_to; + } + + scope_stack_p++; + + if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type)) + { + continue; + } + + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } + +#if JERRY_PARSER_DUMP_BYTE_CODE + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + if (!SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)) + { + if (func_init_opcode == CBC_INIT_ARG_OR_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT)) + { + literal.char_p -= data_p[1]; + + if (!scanner_scope_find_lexical_declaration (context_p, &literal)) + { + func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL; + + if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + { + func_init_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL); + } + } + literal.char_p += data_p[1]; + } + + parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to); + } + + scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC; + scope_stack_p->map_to = context_p->literal_count; + scope_stack_p++; + + scanner_create_unused_literal (context_p, 0); + } + + context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); + context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top; + + if (info_type == SCANNER_TYPE_FUNCTION) + { + context_p->scope_stack_global_end = context_p->scope_stack_top; + } + + if (context_p->register_count < scope_stack_reg_top) + { + context_p->register_count = (uint16_t) scope_stack_reg_top; + } + + if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)) + { + scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p))); + } + parser_flush_cbc (context_p); +} /* scanner_create_variables */ + +/** + * Get location from context. + */ +void +scanner_get_location (scanner_location_t *location_p, /**< location */ + parser_context_t *context_p) /**< context */ +{ + location_p->source_p = context_p->source_p; + location_p->line = context_p->line; + location_p->column = context_p->column; +} /* scanner_get_location */ + +/** + * Set context location. + */ +void +scanner_set_location (parser_context_t *context_p, /**< context */ + scanner_location_t *location_p) /**< location */ +{ + context_p->source_p = location_p->source_p; + context_p->line = location_p->line; + context_p->column = location_p->column; +} /* scanner_set_location */ + +/** + * Get the real map_to value. + */ +uint16_t +scanner_decode_map_to (parser_scope_stack_t *stack_item_p) /**< scope stack item */ +{ + JERRY_ASSERT (stack_item_p->map_from != PARSER_SCOPE_STACK_FUNC); + + uint16_t value = (stack_item_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK); + return (value == 0) ? stack_item_p->map_from : (uint16_t) (value + (PARSER_REGISTER_START - 1)); +} /* scanner_decode_map_to */ + +/** + * Find the given literal index in the scope stack + * and save it the constant literal pool if the literal is register stored + * + * @return given literal index - if literal corresponds to this index is not register stored + * literal index on which literal index has been mapped - otherwise + */ +uint16_t +scanner_save_literal (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + if (literal_index >= PARSER_REGISTER_START) + { + literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1)); + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + do + { + /* Registers must be found in the scope stack. */ + JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p); + scope_stack_p--; + } while (scope_stack_p->map_from == PARSER_SCOPE_STACK_FUNC + || literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK)); + + literal_index = scope_stack_p->map_from; + PARSER_GET_LITERAL (literal_index)->status_flags |= LEXER_FLAG_USED; + } + + return literal_index; +} /* scanner_save_literal */ + +/** + * Checks whether the literal is a const in the current scope. + * + * @return true if the literal is a const, false otherwise + */ +bool +scanner_literal_is_const_reg (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + if (literal_index < PARSER_REGISTER_START) + { + /* Re-assignment of non-register const bindings are detected elsewhere. */ + return false; + } + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1)); + + do + { + /* Registers must be found in the scope stack. */ + JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p); + scope_stack_p--; + } while (scope_stack_p->map_from == PARSER_SCOPE_STACK_FUNC + || literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK)); + + return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_CONST_REG) != 0; +} /* scanner_literal_is_const_reg */ + +/** + * Checks whether the literal is created before. + * + * @return true if the literal is created before, false otherwise + */ +bool +scanner_literal_is_created (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + JERRY_ASSERT (literal_index < PARSER_REGISTER_START); + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + do + { + /* These literals must be found in the scope stack. */ + JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p); + scope_stack_p--; + } while (literal_index != scope_stack_p->map_from); + + JERRY_ASSERT ((scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0); + + return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_LOCAL_CREATED) != 0; +} /* scanner_literal_is_created */ + +/** + * Checks whether the literal exists. + * + * @return true if the literal exists, false otherwise + */ +bool +scanner_literal_exists (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + JERRY_ASSERT (literal_index < PARSER_REGISTER_START); + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + while (scope_stack_p-- > context_p->scope_stack_p) + { + if (scope_stack_p->map_from != PARSER_SCOPE_STACK_FUNC && scanner_decode_map_to (scope_stack_p) == literal_index) + { + return true; + } + } + + return false; +} /* scanner_literal_exists */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.cpp new file mode 100644 index 00000000..c9759921 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.cpp @@ -0,0 +1,3715 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jcontext.h" +#include "js-parser-internal.h" +#include "js-scanner-internal.h" +#include "lit-char-helpers.h" + +#if JERRY_PARSER + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Scan return types. + */ +typedef enum +{ + SCAN_NEXT_TOKEN, /**< get next token after return */ + SCAN_KEEP_TOKEN, /**< keep the current token after return */ +} scan_return_types_t; + +/** + * Checks whether token type is "of". + */ +#define SCANNER_IDENTIFIER_IS_OF() (lexer_token_is_identifier (context_p, "of", 2)) + +JERRY_STATIC_ASSERT ((SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_GENERATOR) == SCAN_STACK_COMPUTED_GENERATOR), + scanner_invalid_conversion_from_literal_pool_generator_to_computed_generator); +JERRY_STATIC_ASSERT ((SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_ASYNC) == SCAN_STACK_COMPUTED_ASYNC), + scanner_invalid_conversion_from_literal_pool_async_to_computed_async); + +JERRY_STATIC_ASSERT ((SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_GENERATOR) == SCANNER_LITERAL_POOL_GENERATOR), + scanner_invalid_conversion_from_computed_generator_to_literal_pool_generator); +JERRY_STATIC_ASSERT ((SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_ASYNC) == SCANNER_LITERAL_POOL_ASYNC), + scanner_invalid_conversion_from_computed_async_to_literal_pool_async); + +/** + * Change scanner mode from primary expression to post primary expression. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_primary_to_post_primary_expression (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p) /* scanner context */ +{ + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == SCAN_STACK_CLASS_FIELD_INITIALIZER + && (context_p->status_flags & PARSER_IS_STRICT))) + { + lexer_scan_identifier (context_p, (lexer_parse_options_t) ((unsigned int) LEXER_PARSE_CHECK_KEYWORDS | (unsigned int) LEXER_PARSE_NO_STRICT_IDENT_ERROR)); + + if (context_p->token.type == LEXER_LITERAL && lexer_compare_literal_to_string (context_p, "static", 6)) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + + return SCAN_KEEP_TOKEN; + } + + return SCAN_NEXT_TOKEN; +} /* scanner_primary_to_post_primary_expression */ + +/** + * Scan primary expression. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_primary_expression (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /* scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + switch (type) + { + case LEXER_KEYW_NEW: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW; + + if (scanner_try_scan_new_target (context_p)) + { + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + + break; + } + case LEXER_DIVIDE: + case LEXER_ASSIGN_DIVIDE: + { + lexer_construct_regexp_object (context_p, true); + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + case LEXER_KEYW_FUNCTION: + { + uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION; +#if JERRY_MODULE_SYSTEM + bool is_export_default = stack_top == SCAN_STACK_EXPORT_DEFAULT; +#endif /* JERRY_MODULE_SYSTEM */ + + if (scanner_context_p->async_source_p != NULL) + { + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + } + + if (lexer_consume_generator (context_p)) + { + status_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + + scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { +#if JERRY_MODULE_SYSTEM + if (is_export_default) + { + lexer_lit_location_t *location_p; + location_p = scanner_add_custom_literal (context_p, + scanner_context_p->active_literal_pool_p->prev_p, + &context_p->token.lit_location); + + scanner_detect_invalid_let (context_p, location_p); + location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET; + } +#endif /* JERRY_MODULE_SYSTEM */ + lexer_next_token (context_p); + } +#if JERRY_MODULE_SYSTEM + else if (is_export_default) + { + lexer_lit_location_t *location_p; + location_p = scanner_add_custom_literal (context_p, + scanner_context_p->active_literal_pool_p->prev_p, + &lexer_default_literal); + location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET; + } +#endif /* JERRY_MODULE_SYSTEM */ + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + case LEXER_LEFT_PAREN: + { + scanner_scan_bracket (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + case LEXER_LEFT_SQUARE: + { + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false); + + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + case LEXER_LEFT_BRACE: + { + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false); + parser_stack_push_uint8 (context_p, 0); + + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + case LEXER_HASHMARK: + { + if (!lexer_scan_private_identifier (context_p)) + { + scanner_raise_error (context_p); + } + + return SCAN_KEEP_TOKEN; + } + case LEXER_TEMPLATE_LITERAL: + { + if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_TEMPLATE_STRING); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + /* The string is a normal string literal. */ + /* FALLTHRU */ + } + case LEXER_LITERAL: + { + const uint8_t *source_p = context_p->source_p; + + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL && lexer_check_arrow (context_p)) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, source_p); + return SCAN_KEEP_TOKEN; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p))) + { + scanner_context_p->async_source_p = source_p; + scanner_check_async_function (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { +#if JERRY_MODULE_SYSTEM + if (stack_top == SCAN_STACK_EXPORT_DEFAULT) + { + lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p); + location_p->type |= (SCANNER_LITERAL_IS_USED | SCANNER_LITERAL_IS_VAR); + scanner_detect_eval_call (context_p, scanner_context_p); + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } +#endif /* JERRY_MODULE_SYSTEM */ + + scanner_add_reference (context_p, scanner_context_p); + } + /* FALLTHRU */ + } + case LEXER_KEYW_THIS: + case LEXER_LIT_TRUE: + case LEXER_LIT_FALSE: + case LEXER_LIT_NULL: + { + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + case LEXER_KEYW_SUPER: + { + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE; + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + case LEXER_KEYW_CLASS: + { + scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_EXPRESSION); + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + return SCAN_KEEP_TOKEN; + } + break; + } + case LEXER_RIGHT_SQUARE: + { + if (stack_top != SCAN_STACK_ARRAY_LITERAL) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case LEXER_THREE_DOTS: + { + /* Elision or spread arguments */ + if (stack_top != SCAN_STACK_PAREN_EXPRESSION && stack_top != SCAN_STACK_ARRAY_LITERAL) + { + scanner_raise_error (context_p); + } + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + case LEXER_COMMA: + { + if (stack_top != SCAN_STACK_ARRAY_LITERAL) + { + scanner_raise_error (context_p); + } + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context_p->binding_type != SCANNER_BINDING_NONE) + { + scanner_context_p->mode = SCAN_MODE_BINDING; + } + + break; + } + case LEXER_KEYW_YIELD: + { + lexer_next_token (context_p); + + if (lexer_check_yield_no_arg (context_p)) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + + if (context_p->token.type == LEXER_MULTIPLY) + { + return SCAN_NEXT_TOKEN; + } + return SCAN_KEEP_TOKEN; + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_DOT) + { + scanner_check_import_meta (context_p); + } + else if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } +#endif /* JERRY_MODULE_SYSTEM */ + case LEXER_RIGHT_PAREN: + { + if (stack_top == SCAN_STACK_PAREN_EXPRESSION) + { + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + return scanner_primary_to_post_primary_expression (context_p, scanner_context_p); + } + /* FALLTHRU */ + } + default: + { + scanner_raise_error (context_p); + } + } + return SCAN_NEXT_TOKEN; +} /* scanner_scan_primary_expression */ + +/** + * Scan the tokens after the primary expression. + * + * @return true for break, false for fall through + */ +static bool +scanner_scan_post_primary_expression (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + switch (type) + { + case LEXER_DOT: + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + + if (context_p->token.type == LEXER_HASHMARK) + { + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + return true; + } + case LEXER_LEFT_PAREN: + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + case LEXER_TEMPLATE_LITERAL: + { + if (JERRY_UNLIKELY (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_push_uint8 (context_p, SCAN_STACK_TAGGED_TEMPLATE_LITERAL); + } + return true; + } + case LEXER_LEFT_SQUARE: + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PROPERTY_ACCESSOR); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + case LEXER_INCREASE: + case LEXER_DECREASE: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + + if (context_p->token.flags & LEXER_WAS_NEWLINE) + { + return false; + } + + lexer_next_token (context_p); + type = (lexer_token_type_t) context_p->token.type; + + if (type != LEXER_QUESTION_MARK) + { + break; + } + /* FALLTHRU */ + } + case LEXER_QUESTION_MARK: + { + parser_stack_push_uint8 (context_p, SCAN_STACK_COLON_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + default: + { + break; + } + } + + if (LEXER_IS_BINARY_OP_TOKEN (type) && (type != LEXER_KEYW_IN || !SCANNER_IS_FOR_START (stack_top))) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; + } + + return false; +} /* scanner_scan_post_primary_expression */ + +/** + * Scan the tokens after the primary expression. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + if (type == LEXER_COMMA) + { + switch (stack_top) + { + case SCAN_STACK_VAR: + case SCAN_STACK_LET: + case SCAN_STACK_CONST: + case SCAN_STACK_FOR_VAR_START: + case SCAN_STACK_FOR_LET_START: + case SCAN_STACK_FOR_CONST_START: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COLON_EXPRESSION: + { + scanner_raise_error (context_p); + break; + } + case SCAN_STACK_BINDING_INIT: + case SCAN_STACK_BINDING_LIST_INIT: + { + break; + } + case SCAN_STACK_ARROW_ARGUMENTS: + { + lexer_next_token (context_p); + scanner_check_arrow_arg (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_ARROW_EXPRESSION: + { + break; + } + case SCAN_STACK_CLASS_FIELD_INITIALIZER: + { + scanner_raise_error (context_p); + break; + } + case SCAN_STACK_FUNCTION_PARAMETERS: + { + scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS; + parser_stack_pop_uint8 (context_p); + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_ARRAY_LITERAL: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context_p->binding_type != SCANNER_BINDING_NONE) + { + scanner_context_p->mode = SCAN_MODE_BINDING; + } + + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_OBJECT_LITERAL: + { + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + default: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + } + } + + switch (stack_top) + { + case SCAN_STACK_WITH_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + parser_stack_pop_uint8 (context_p); + + uint16_t status_flags = scanner_context_p->active_literal_pool_p->status_flags; + parser_stack_push_uint8 (context_p, (status_flags & SCANNER_LITERAL_POOL_IN_WITH) ? 1 : 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_WITH_STATEMENT); + status_flags |= SCANNER_LITERAL_POOL_IN_WITH; + scanner_context_p->active_literal_pool_p->status_flags = status_flags; + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_DO_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_WHILE_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_source_start_t source_start; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_WHILE; + + scanner_get_location (&location_info_p->location, context_p); + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_PAREN_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC) + { + scanner_add_async_literal (context_p, scanner_context_p); + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_STATEMENT_WITH_EXPR: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_IF_STATEMENT) + { + scanner_check_function_after_if (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_BINDING_LIST_INIT: + { + parser_stack_pop_uint8 (context_p); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_LET || context_p->stack_top_uint8 == SCAN_STACK_CONST + || context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START + || context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START + || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS + || context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS); + + scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p; + + while (item_p != NULL) + { + if (item_p->literal_p->type & SCANNER_LITERAL_IS_USED) + { + item_p->literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + item_p = item_p->next_p; + } + + scanner_pop_binding_list (scanner_context_p); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_BINDING_INIT: + { + scanner_binding_literal_t binding_literal; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_LET || context_p->stack_top_uint8 == SCAN_STACK_CONST + || context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START + || context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START + || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS + || context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS); + + JERRY_ASSERT (SCANNER_NEEDS_BINDING_LIST (scanner_context_p->binding_type) + || (stack_top != SCAN_STACK_ARRAY_LITERAL && stack_top != SCAN_STACK_OBJECT_LITERAL)); + + if (binding_literal.literal_p->type & SCANNER_LITERAL_IS_USED) + { + binding_literal.literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_VAR: + case SCAN_STACK_LET: + case SCAN_STACK_CONST: + { +#if JERRY_MODULE_SYSTEM + scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; +#endif /* JERRY_MODULE_SYSTEM */ + + parser_stack_pop_uint8 (context_p); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_FOR_VAR_START: + case SCAN_STACK_FOR_LET_START: + case SCAN_STACK_FOR_CONST_START: + case SCAN_STACK_FOR_START: + { + if (type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ()) + { + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t)); + + scanner_location_info_t *location_info; + location_info = (scanner_location_info_t *) scanner_insert_info (context_p, + for_statement.u.source_p, + sizeof (scanner_location_info_t)); + location_info->info.type = (type == LEXER_KEYW_IN) ? SCANNER_TYPE_FOR_IN : SCANNER_TYPE_FOR_OF; + + if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK_EARLY); + } + scanner_get_location (&location_info->location, context_p); + + parser_stack_push_uint8 (context_p, SCAN_STACK_STATEMENT_WITH_EXPR); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + + if (type != LEXER_SEMICOLON) + { + break; + } + + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, NULL, sizeof (scanner_for_statement_t)); + + if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK); + } + + for_statement.u.source_p = context_p->source_p; + parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_CONDITION); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_SEMICOLON) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + type = LEXER_SEMICOLON; + /* FALLTHRU */ + } + case SCAN_STACK_FOR_CONDITION: + { + if (type != LEXER_SEMICOLON) + { + break; + } + + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t)); + + scanner_for_info_t *for_info_p; + for_info_p = + (scanner_for_info_t *) scanner_insert_info (context_p, for_statement.u.source_p, sizeof (scanner_for_info_t)); + for_info_p->info.type = SCANNER_TYPE_FOR; + + scanner_get_location (&for_info_p->expression_location, context_p); + for_info_p->end_location.source_p = NULL; + + for_statement.u.for_info_p = for_info_p; + + parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_EXPRESSION); + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + type = LEXER_RIGHT_PAREN; + /* FALLTHRU */ + } + case SCAN_STACK_FOR_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_for_statement_t for_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t)); + + scanner_get_location (&for_statement.u.for_info_p->end_location, context_p); + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_SWITCH_EXPRESSION: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + break; + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p - 1; + + parser_stack_pop_uint8 (context_p); + + scanner_switch_statement_t switch_statement = scanner_context_p->active_switch_statement; + parser_stack_push (context_p, &switch_statement, sizeof (scanner_switch_statement_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_SWITCH_BLOCK); + + scanner_switch_info_t *switch_info_p; + switch_info_p = + (scanner_switch_info_t *) scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_switch_info_t)); + switch_info_p->info.type = SCANNER_TYPE_SWITCH; + switch_info_p->case_p = NULL; + scanner_context_p->active_switch_statement.last_case_p = &switch_info_p->case_p; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_KEYW_CASE + && context_p->token.type != LEXER_KEYW_DEFAULT) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_CASE_STATEMENT: + { + if (type != LEXER_COLON) + { + break; + } + + scanner_source_start_t source_start; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_CASE; + + scanner_get_location (&location_info_p->location, context_p); + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COLON_EXPRESSION: + { + if (type != LEXER_COLON) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_pop_uint8 (context_p); + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_ARRAY_LITERAL: + case SCAN_STACK_OBJECT_LITERAL: + { + if ((stack_top == SCAN_STACK_ARRAY_LITERAL && type != LEXER_RIGHT_SQUARE) + || (stack_top == SCAN_STACK_OBJECT_LITERAL && type != LEXER_RIGHT_BRACE)) + { + break; + } + + scanner_source_start_t source_start; + uint8_t binding_type = scanner_context_p->binding_type; + uint8_t object_literal_flags = 0; + + parser_stack_pop_uint8 (context_p); + + if (stack_top == SCAN_STACK_OBJECT_LITERAL) + { + object_literal_flags = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + } + + scanner_context_p->binding_type = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + + lexer_next_token (context_p); + + stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + + if (binding_type == SCANNER_BINDING_CATCH && stack_top == SCAN_STACK_CATCH_STATEMENT) + { + scanner_pop_binding_list (scanner_context_p); + + if (object_literal_flags != 0) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LITERAL_FLAGS; + info_p->u8_arg = object_literal_flags; + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + if (stack_top == SCAN_STACK_FOR_START_PATTERN) + { + JERRY_ASSERT (binding_type == SCANNER_BINDING_NONE); + + parser_stack_change_last_uint8 (context_p, SCAN_STACK_FOR_START); + + if (context_p->token.type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ()) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LITERAL_FLAGS; + info_p->u8_arg = object_literal_flags | SCANNER_LITERAL_DESTRUCTURING_FOR; + return SCAN_KEEP_TOKEN; + } + } + + if (context_p->token.type != LEXER_ASSIGN) + { + if (SCANNER_NEEDS_BINDING_LIST (binding_type)) + { + scanner_pop_binding_list (scanner_context_p); + } + + if ((stack_top == SCAN_STACK_ARRAY_LITERAL || stack_top == SCAN_STACK_OBJECT_LITERAL) + && (binding_type == SCANNER_BINDING_NONE || binding_type == SCANNER_BINDING_ARROW_ARG) + && context_p->token.type != LEXER_EOS && context_p->token.type != LEXER_COMMA + && context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_RIGHT_SQUARE) + { + object_literal_flags |= SCANNER_LITERAL_NO_DESTRUCTURING; + } + + if (object_literal_flags != 0) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LITERAL_FLAGS; + info_p->u8_arg = object_literal_flags; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_INITIALIZER; + location_info_p->info.u8_arg = object_literal_flags; + scanner_get_location (&location_info_p->location, context_p); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (SCANNER_NEEDS_BINDING_LIST (binding_type)) + { + scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p; + + while (item_p != NULL) + { + item_p->literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_USED; + item_p = item_p->next_p; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_LIST_INIT); + } + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_PROPERTY_ACCESSOR: + { + if (type != LEXER_RIGHT_SQUARE) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + parser_stack_pop_uint8 (context_p); + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COMPUTED_PROPERTY: + { + if (type != LEXER_RIGHT_SQUARE) + { + break; + } + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + + parser_stack_pop_uint8 (context_p); + stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + + if (stack_top == SCAN_STACK_FUNCTION_PROPERTY) + { + scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + + if (stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR || stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR) + { + JERRY_ASSERT (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION); + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_push_class_field_initializer (context_p, scanner_context_p); + return SCAN_NEXT_TOKEN; + } + + scanner_context_p->mode = + (context_p->token.type != LEXER_SEMICOLON ? SCAN_MODE_CLASS_BODY_NO_SCAN : SCAN_MODE_CLASS_BODY); + return SCAN_KEEP_TOKEN; + } + + JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION); + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type != LEXER_COLON) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context_p->binding_type != SCANNER_BINDING_NONE) + { + scanner_context_p->mode = SCAN_MODE_BINDING; + } + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_COMPUTED_GENERATOR: + case SCAN_STACK_COMPUTED_ASYNC: + case SCAN_STACK_COMPUTED_ASYNC_GENERATOR: + { + if (type != LEXER_RIGHT_SQUARE) + { + break; + } + + lexer_next_token (context_p); + parser_stack_pop_uint8 (context_p); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL + || context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PROPERTY); + + uint16_t status_flags = (uint16_t) (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_GENERATOR + | SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (stack_top)); + + scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_TEMPLATE_STRING: + case SCAN_STACK_TAGGED_TEMPLATE_LITERAL: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + context_p->source_p--; + context_p->column--; + lexer_parse_string (context_p, LEXER_STRING_NO_OPTS); + + if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + } + else + { + parser_stack_pop_uint8 (context_p); + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + } + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_ARROW_ARGUMENTS: + { + if (type != LEXER_RIGHT_PAREN) + { + break; + } + + scanner_check_arrow (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_ARROW_EXPRESSION: + { + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + lexer_update_await_yield (context_p, context_p->status_flags); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_CLASS_EXTENDS: + { + if (type != LEXER_LEFT_BRACE) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_CLASS_BODY; + parser_stack_pop_uint8 (context_p); + + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_CLASS_FIELD_INITIALIZER: + { + scanner_source_start_t source_start; + const uint8_t *source_p = NULL; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t)); + scanner_pop_literal_pool (context_p, scanner_context_p); + scanner_context_p->mode = SCAN_MODE_CLASS_BODY_NO_SCAN; + + switch (type) + { + case LEXER_SEMICOLON: + { + source_p = context_p->source_p - 1; + scanner_context_p->mode = SCAN_MODE_CLASS_BODY; + break; + } + case LEXER_RIGHT_BRACE: + { + source_p = context_p->source_p - 1; + break; + } + default: + { + if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + break; + } + + if (type == LEXER_LEFT_SQUARE) + { + source_p = context_p->source_p - 1; + break; + } + + if (type == LEXER_LITERAL) + { + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + || context_p->token.lit_location.type == LEXER_NUMBER_LITERAL) + { + source_p = context_p->token.lit_location.char_p; + } + else if (context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + source_p = context_p->token.lit_location.char_p - 1; + } + break; + } + + if (type == context_p->token.keyword_type && type != LEXER_EOS) + { + /* Convert keyword to literal. */ + source_p = context_p->token.lit_location.char_p; + context_p->token.type = LEXER_LITERAL; + } + break; + } + } + + if (JERRY_UNLIKELY (source_p == NULL)) + { + scanner_raise_error (context_p); + } + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + source_start.source_p, + sizeof (scanner_location_info_t)); + location_info_p->info.type = SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END; + location_info_p->location.source_p = source_p; + location_info_p->location.line = context_p->token.line; + location_info_p->location.column = context_p->token.column; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_FUNCTION_PARAMETERS: + { + parser_stack_pop_uint8 (context_p); + + if (type != LEXER_RIGHT_PAREN && (type != LEXER_EOS || context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION)) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS; + return SCAN_KEEP_TOKEN; + } + default: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_KEEP_TOKEN; + } + } + + scanner_raise_error (context_p); + return SCAN_NEXT_TOKEN; +} /* scanner_scan_primary_expression_end */ + +/** + * Scan statements. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_statement (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type, /**< current token type */ + scan_stack_modes_t stack_top) /**< current stack top */ +{ + switch (type) + { + case LEXER_SEMICOLON: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_KEEP_TOKEN; + } + case LEXER_LEFT_BRACE: + { + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_DO: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_DO_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_TRY: + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + parser_stack_push_uint8 (context_p, SCAN_STACK_TRY_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_DEBUGGER: + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_IF: + case LEXER_KEYW_WITH: + case LEXER_KEYW_SWITCH: + { + lexer_next_token (context_p); + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + uint8_t mode = SCAN_STACK_STATEMENT_WITH_EXPR; + + if (type == LEXER_KEYW_IF) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_IF_STATEMENT); + } + else if (type == LEXER_KEYW_WITH) + { + mode = SCAN_STACK_WITH_EXPRESSION; + } + else if (type == LEXER_KEYW_SWITCH) + { + mode = SCAN_STACK_SWITCH_EXPRESSION; + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + parser_stack_push_uint8 (context_p, mode); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_WHILE: + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_WHILE_EXPRESSION); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_FOR: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_KEYW_AWAIT) + { + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + scanner_for_statement_t for_statement; + for_statement.u.source_p = context_p->source_p; + uint8_t stack_mode = SCAN_STACK_FOR_START; + scan_return_types_t return_type = SCAN_KEEP_TOKEN; + + lexer_next_token (context_p); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + const uint8_t *source_p = context_p->source_p; + + switch (context_p->token.type) + { + case LEXER_SEMICOLON: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + break; + } + case LEXER_KEYW_VAR: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + stack_mode = SCAN_STACK_FOR_VAR_START; + return_type = SCAN_NEXT_TOKEN; + break; + } + case LEXER_LEFT_BRACE: + case LEXER_LEFT_SQUARE: + { + stack_mode = SCAN_STACK_FOR_START_PATTERN; + break; + } + case LEXER_LITERAL: + { + if (!lexer_token_is_let (context_p)) + { + break; + } + + parser_line_counter_t line = context_p->line; + parser_line_counter_t column = context_p->column; + + if (lexer_check_arrow (context_p)) + { + context_p->source_p = source_p; + context_p->line = line; + context_p->column = column; + context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES; + break; + } + + lexer_next_token (context_p); + + type = (lexer_token_type_t) context_p->token.type; + + if (type != LEXER_LEFT_SQUARE && type != LEXER_LEFT_BRACE + && (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)) + { + scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LET_EXPRESSION; + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + break; + } + + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + /* FALLTHRU */ + } + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + { + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = source_p; + + if (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION) + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + return_type = SCAN_NEXT_TOKEN; + } + + stack_mode = + ((context_p->token.type == LEXER_KEYW_CONST) ? SCAN_STACK_FOR_CONST_START : SCAN_STACK_FOR_LET_START); + break; + } + } + + parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t)); + parser_stack_push_uint8 (context_p, stack_mode); + return return_type; + } + case LEXER_KEYW_VAR: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_VAR); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_LET: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_LET); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_CONST: + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_CONST); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_THROW: + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_RETURN: + { + lexer_next_token (context_p); + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type != LEXER_SEMICOLON + && context_p->token.type != LEXER_EOS && context_p->token.type != LEXER_RIGHT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + return SCAN_KEEP_TOKEN; + } + case LEXER_KEYW_BREAK: + case LEXER_KEYW_CONTINUE: + { + lexer_next_token (context_p); + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + return SCAN_NEXT_TOKEN; + } + return SCAN_KEEP_TOKEN; + } + case LEXER_KEYW_CASE: + case LEXER_KEYW_DEFAULT: + { + if (stack_top != SCAN_STACK_SWITCH_BLOCK) + { + scanner_raise_error (context_p); + } + + scanner_case_info_t *case_info_p; + case_info_p = (scanner_case_info_t *) scanner_malloc (context_p, sizeof (scanner_case_info_t)); + + *(scanner_context_p->active_switch_statement.last_case_p) = case_info_p; + scanner_context_p->active_switch_statement.last_case_p = &case_info_p->next_p; + + case_info_p->next_p = NULL; + scanner_get_location (&case_info_p->location, context_p); + + if (type == LEXER_KEYW_DEFAULT) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_COLON) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_CASE_STATEMENT); + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_FUNCTION: + { + uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_FUNCTION_STATEMENT; + + if (scanner_context_p->async_source_p != NULL) + { + scanner_context_p->status_flags |= SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION; + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_MULTIPLY) + { + status_flags |= SCANNER_LITERAL_POOL_GENERATOR; + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL); + + if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL) + && (literal_p->type & mask) != (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + && (literal_p->type & mask) != SCANNER_LITERAL_IS_LOCAL_FUNC) + { + scanner_raise_redeclaration_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + if (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) + && (literal_p->type & (SCANNER_LITERAL_IS_VAR))) + { + scanner_raise_redeclaration_error (context_p); + } + + literal_p->type |= SCANNER_LITERAL_IS_LOCAL_FUNC; + + scanner_context_p->status_flags &= (uint16_t) ~SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION; + + scanner_push_literal_pool (context_p, scanner_context_p, status_flags); + + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT); + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_CLASS: + { + lexer_lit_location_t *literal_p; + literal_p = scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_STATEMENT); + + if (literal_p == NULL) + { + scanner_raise_error (context_p); + } + + scanner_detect_invalid_let (context_p, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_LET; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + +#if JERRY_MODULE_SYSTEM + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; + } +#endif /* JERRY_MODULE_SYSTEM */ + + return SCAN_NEXT_TOKEN; + } +#if JERRY_MODULE_SYSTEM + case LEXER_KEYW_IMPORT: + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_DOT) + { + scanner_check_import_meta (context_p); + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + if (stack_top != SCAN_STACK_SCRIPT) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + return SCAN_NEXT_TOKEN; + } + + bool parse_imports = true; + + if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + scanner_detect_invalid_let (context_p, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG; + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + } + else + { + parse_imports = false; + } + } + + if (parse_imports) + { + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_next_token (context_p); + if (!lexer_token_is_identifier (context_p, "as", 2)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + scanner_detect_invalid_let (context_p, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG; + + lexer_next_token (context_p); + } + else if (context_p->token.type == LEXER_LEFT_BRACE) + { + lexer_next_token (context_p); + + while (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + const uint8_t *source_p = context_p->source_p; + + if (lexer_check_next_character (context_p, LIT_CHAR_LOWERCASE_A)) + { + lexer_next_token (context_p); + + if (!lexer_token_is_identifier (context_p, "as", 2)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + source_p = context_p->source_p; + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); + + if (literal_p->type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_LOCAL)) + { + context_p->source_p = source_p; + scanner_raise_redeclaration_error (context_p); + } + + if (literal_p->type & SCANNER_LITERAL_IS_FUNC) + { + literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC; + } + + literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_COMMA) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + } + + lexer_next_token (context_p); + } + else + { + scanner_raise_error (context_p); + } + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type != LEXER_STRING_LITERAL) + { + scanner_raise_error (context_p); + } + + return SCAN_NEXT_TOKEN; + } + case LEXER_KEYW_EXPORT: + { + if (stack_top != SCAN_STACK_SCRIPT) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_KEYW_DEFAULT) + { + lexer_next_token (context_p); + parser_stack_push_uint8 (context_p, SCAN_STACK_EXPORT_DEFAULT); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_END; + + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_next_token (context_p); + + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + scanner_raise_error (context_p); + } + + return SCAN_NEXT_TOKEN; + } + + scanner_source_start_t source_start; + source_start.source_p = context_p->source_p; + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + lexer_next_token (context_p); + + while (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (lexer_token_is_identifier (context_p, "as", 2)) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + + if (context_p->token.type != LEXER_RIGHT_BRACE) + { + if (context_p->token.type != LEXER_COMMA) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + } + } + + lexer_next_token (context_p); + + if (!lexer_token_is_identifier (context_p, "from", 4)) + { + return SCAN_KEEP_TOKEN; + } + + scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_EXPORT_MODULE_SPECIFIER; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL) + { + scanner_raise_error (context_p); + } + + return SCAN_NEXT_TOKEN; + } + + switch (context_p->token.type) + { + case LEXER_KEYW_CLASS: + case LEXER_KEYW_LET: + case LEXER_KEYW_CONST: + case LEXER_KEYW_VAR: + { + scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IN_EXPORT; + break; + } + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_KEEP_TOKEN; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + break; + } + } + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + if (JERRY_UNLIKELY (lexer_check_next_character (context_p, LIT_CHAR_COLON))) + { + lexer_consume_next_character (context_p); + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_NEXT_TOKEN; + } + + JERRY_ASSERT (context_p->token.flags & LEXER_NO_SKIP_SPACES); + + /* The colon needs to be checked first because the parser also checks + * it first, and this check skips the spaces which affects source_p. */ + if (JERRY_UNLIKELY (lexer_check_arrow (context_p))) + { + scanner_scan_simple_arrow (context_p, scanner_context_p, context_p->source_p); + return SCAN_KEEP_TOKEN; + } + + if (JERRY_UNLIKELY (lexer_token_is_let (context_p))) + { + lexer_lit_location_t let_literal = context_p->token.lit_location; + const uint8_t *source_p = context_p->source_p; + + lexer_next_token (context_p); + + type = (lexer_token_type_t) context_p->token.type; + + if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE + || (type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)) + { + scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT; + parser_stack_push_uint8 (context_p, SCAN_STACK_LET); + return SCAN_KEEP_TOKEN; + } + + scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_LET_EXPRESSION; + + lexer_lit_location_t *lit_location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &let_literal); + lit_location_p->type |= SCANNER_LITERAL_IS_USED; + + if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + lit_location_p->type |= SCANNER_LITERAL_NO_REG; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_KEEP_TOKEN; + } + + if (JERRY_UNLIKELY (lexer_token_is_async (context_p))) + { + scanner_context_p->async_source_p = context_p->source_p; + + if (scanner_check_async_function (context_p, scanner_context_p)) + { + scanner_context_p->mode = SCAN_MODE_STATEMENT; + } + return SCAN_KEEP_TOKEN; + } + + scanner_add_reference (context_p, scanner_context_p); + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + + return SCAN_KEEP_TOKEN; +} /* scanner_scan_statement */ + +/** + * Scan statement terminator. + * + * @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing + */ +static scan_return_types_t +scanner_scan_statement_end (parser_context_t *context_p, /**< context */ + scanner_context_t *scanner_context_p, /**< scanner context */ + lexer_token_type_t type) /**< current token type */ +{ + bool terminator_found = false; + + if (type == LEXER_SEMICOLON) + { + lexer_next_token (context_p); + terminator_found = true; + } + + while (true) + { + type = (lexer_token_type_t) context_p->token.type; + + switch (context_p->stack_top_uint8) + { + case SCAN_STACK_SCRIPT: + case SCAN_STACK_SCRIPT_FUNCTION: + { + if (type == LEXER_EOS) + { + return SCAN_NEXT_TOKEN; + } + break; + } + case SCAN_STACK_BLOCK_STATEMENT: + case SCAN_STACK_CLASS_STATEMENT: + case SCAN_STACK_FUNCTION_STATEMENT: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + if (context_p->stack_top_uint8 != SCAN_STACK_CLASS_STATEMENT) + { + scanner_pop_literal_pool (context_p, scanner_context_p); + } + + terminator_found = true; + parser_stack_pop_uint8 (context_p); +#if JERRY_MODULE_SYSTEM + scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; +#endif /* JERRY_MODULE_SYSTEM */ + lexer_next_token (context_p); + continue; + } + case SCAN_STACK_FUNCTION_EXPRESSION: + case SCAN_STACK_FUNCTION_ARROW: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_ARROW) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + } + + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + +#if JERRY_MODULE_SYSTEM + if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT) + { + terminator_found = true; + parser_stack_pop_uint8 (context_p); + lexer_next_token (context_p); + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_FUNCTION_PROPERTY: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + bool has_super_reference = + (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE) != 0; + + scanner_pop_literal_pool (context_p, scanner_context_p); + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR + || context_p->stack_top_uint8 == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR) + { + scanner_context_p->mode = SCAN_MODE_CLASS_BODY; + return SCAN_KEEP_TOKEN; + } + + if (has_super_reference && context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL) + { + *parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_SUPER; + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type != LEXER_COMMA) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_SWITCH_BLOCK: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + scanner_switch_statement_t switch_statement; + + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &switch_statement, sizeof (scanner_switch_statement_t)); + + scanner_context_p->active_switch_statement = switch_statement; + + scanner_pop_literal_pool (context_p, scanner_context_p); + + terminator_found = true; + lexer_next_token (context_p); + continue; + } + case SCAN_STACK_IF_STATEMENT: + { + parser_stack_pop_uint8 (context_p); + + if (type == LEXER_KEYW_ELSE && (terminator_found || (context_p->token.flags & LEXER_WAS_NEWLINE))) + { + scanner_check_function_after_if (context_p, scanner_context_p); + return SCAN_KEEP_TOKEN; + } + + continue; + } + case SCAN_STACK_WITH_STATEMENT: + { + scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p; + + JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH); + + parser_stack_pop_uint8 (context_p); + + if (context_p->stack_top_uint8 == 0) + { + literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_WITH; + } + + parser_stack_pop_uint8 (context_p); + continue; + } + case SCAN_STACK_DO_STATEMENT: + { + parser_stack_pop_uint8 (context_p); + + if (type != LEXER_KEYW_WHILE || (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE))) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_DO_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return SCAN_NEXT_TOKEN; + } + case SCAN_STACK_DO_EXPRESSION: + { + parser_stack_pop_uint8 (context_p); + terminator_found = true; + continue; + } + case SCAN_STACK_CLASS_STATIC_BLOCK: + { + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + scanner_pop_literal_pool (context_p, scanner_context_p); + scanner_source_start_t start_range; + parser_stack_pop_uint8 (context_p); + parser_stack_pop (context_p, &start_range, sizeof (scanner_source_start_t)); + + scanner_context_p->mode = SCAN_MODE_CLASS_BODY_NO_SCAN; + + scanner_location_info_t *location_info_p; + location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p, + start_range.source_p, + sizeof (scanner_location_info_t)); + + location_info_p->info.type = SCANNER_TYPE_CLASS_STATIC_BLOCK_END; + location_info_p->location.source_p = context_p->source_p; + location_info_p->location.line = context_p->token.line; + location_info_p->location.column = context_p->token.column; + + lexer_scan_identifier (context_p, (lexer_parse_options_t) ((unsigned int) LEXER_PARSE_CHECK_KEYWORDS | (unsigned int) LEXER_PARSE_NO_STRICT_IDENT_ERROR)); + return SCAN_KEEP_TOKEN; + } + case SCAN_STACK_PRIVATE_BLOCK_EARLY: + { + parser_list_iterator_t literal_iterator; + lexer_lit_location_t *literal_p; + + parser_list_iterator_init (&scanner_context_p->active_literal_pool_p->literal_pool, &literal_iterator); + + while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) + { + if ((literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)) + && (literal_p->type & SCANNER_LITERAL_IS_USED)) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + } + /* FALLTHRU */ + } + case SCAN_STACK_PRIVATE_BLOCK: + { + parser_stack_pop_uint8 (context_p); + scanner_pop_literal_pool (context_p, scanner_context_p); + continue; + } +#if JERRY_MODULE_SYSTEM + case SCAN_STACK_EXPORT_DEFAULT: + { + parser_stack_pop_uint8 (context_p); + lexer_lit_location_t *location_p = + scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &lexer_default_literal); + location_p->type |= SCANNER_LITERAL_IS_VAR; + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + default: + { + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_TRY_STATEMENT + || context_p->stack_top_uint8 == SCAN_STACK_CATCH_STATEMENT); + + if (type != LEXER_RIGHT_BRACE) + { + break; + } + + uint8_t stack_top = context_p->stack_top_uint8; + parser_stack_pop_uint8 (context_p); + lexer_next_token (context_p); + + scanner_pop_literal_pool (context_p, scanner_context_p); + + /* A finally statement is optional after a try or catch statement. */ + if (context_p->token.type == LEXER_KEYW_FINALLY) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT); + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + if (stack_top == SCAN_STACK_CATCH_STATEMENT) + { + terminator_found = true; + continue; + } + + /* A catch statement must be present after a try statement unless a finally is provided. */ + if (context_p->token.type != LEXER_KEYW_CATCH) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + scanner_literal_pool_t *literal_pool_p; + literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0); + literal_pool_p->source_p = context_p->source_p; + parser_stack_push_uint8 (context_p, SCAN_STACK_CATCH_STATEMENT); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + + if (context_p->token.type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_CATCH, false); + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context_p->mode = SCAN_MODE_BINDING; + return SCAN_NEXT_TOKEN; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME; + return SCAN_KEEP_TOKEN; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *lit_location_p = scanner_add_literal (context_p, scanner_context_p); + lit_location_p->type |= SCANNER_LITERAL_IS_LOCAL; + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + return SCAN_NEXT_TOKEN; + } + } + + if (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + scanner_raise_error (context_p); + } + + scanner_context_p->mode = SCAN_MODE_STATEMENT; + return SCAN_KEEP_TOKEN; + } +} /* scanner_scan_statement_end */ + +/** + * Scan the whole source code. + */ +void JERRY_ATTR_NOINLINE +scanner_scan_all (parser_context_t *context_p) /**< context */ +{ + scanner_context_t scanner_context; + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Scanning start ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + scanner_context.context_status_flags = context_p->status_flags; + scanner_context.status_flags = SCANNER_CONTEXT_NO_FLAGS; + scanner_context.binding_type = SCANNER_BINDING_NONE; + scanner_context.active_binding_list_p = NULL; + scanner_context.active_literal_pool_p = NULL; + scanner_context.active_switch_statement.last_case_p = NULL; + scanner_context.end_arguments_p = NULL; + scanner_context.async_source_p = NULL; + + /* This assignment must be here because of Apple compilers. */ + context_p->u.scanner_context_p = &scanner_context; + context_p->global_status_flags |= ECMA_PARSE_INTERNAL_PRE_SCANNING; + + parser_stack_init (context_p); + + PARSER_TRY (context_p->try_buffer) + { + if (context_p->arguments_start_p == NULL) + { + context_p->source_p = context_p->source_start_p; + context_p->source_end_p = context_p->source_start_p + context_p->source_size; + + uint16_t status_flags = + (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_NO_ARGUMENTS | SCANNER_LITERAL_POOL_CAN_EVAL); + + if (context_p->status_flags & PARSER_IS_STRICT) + { + status_flags |= SCANNER_LITERAL_POOL_IS_STRICT; + } + + scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, &scanner_context, status_flags); + literal_pool_p->source_p = context_p->source_start_p; + + parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT); + + lexer_next_token (context_p); + scanner_check_directives (context_p, &scanner_context); + } + else + { + context_p->source_p = context_p->arguments_start_p; + context_p->source_end_p = context_p->arguments_start_p + context_p->arguments_size; + + uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION; + + if (context_p->status_flags & PARSER_IS_STRICT) + { + status_flags |= SCANNER_LITERAL_POOL_IS_STRICT; + } + + if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION) + { + status_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION) + { + status_flags |= SCANNER_LITERAL_POOL_ASYNC; + } + + scanner_push_literal_pool (context_p, &scanner_context, status_flags); + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT_FUNCTION); + + /* Faking the first token. */ + context_p->token.type = LEXER_LEFT_PAREN; + } + + while (true) + { + lexer_token_type_t type = (lexer_token_type_t) context_p->token.type; + scan_stack_modes_t stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; + + switch (scanner_context.mode) + { + case SCAN_MODE_PRIMARY_EXPRESSION: + { + if (type == LEXER_ADD || type == LEXER_SUBTRACT || LEXER_IS_UNARY_OP_TOKEN (type)) + { + break; + } + /* FALLTHRU */ + } + case SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW: + { + if (scanner_scan_primary_expression (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN) + { + continue; + } + break; + } + case SCAN_MODE_CLASS_DECLARATION: + { + if (context_p->token.type == LEXER_KEYW_EXTENDS) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXTENDS); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + else if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_CLASS_BODY; + /* FALLTHRU */ + } + case SCAN_MODE_CLASS_BODY: + { + lexer_skip_empty_statements (context_p); + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + /* FALLTHRU */ + } + case SCAN_MODE_CLASS_BODY_NO_SCAN: + { + JERRY_ASSERT (stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR + || stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR); + JERRY_ASSERT (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME); + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + parser_stack_pop_uint8 (context_p); + + scanner_class_info_t *private_members_p; + parser_stack_pop (context_p, &private_members_p, sizeof (scanner_class_info_t *)); + + private_members_p->info.u8_arg |= SCANNER_SUCCESSFUL_CLASS_SCAN; + + scanner_pop_literal_pool (context_p, &scanner_context); + + JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT + || context_p->stack_top_uint8 == SCAN_STACK_CLASS_EXPRESSION); + + if (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT) + { + /* The token is kept to disallow consuming a semicolon after it. */ + scanner_context.mode = SCAN_MODE_STATEMENT_END; + continue; + } + + scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + parser_stack_pop_uint8 (context_p); + +#if JERRY_MODULE_SYSTEM + if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT) + { + /* The token is kept to disallow consuming a semicolon after it. */ + parser_stack_change_last_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT); + scanner_context.mode = SCAN_MODE_STATEMENT_END; + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + break; + } + + bool is_private = false; + scanner_private_field_flags_t private_field_flags = SCANNER_PRIVATE_FIELD_PROPERTY; + + if (context_p->token.type == LEXER_HASHMARK) + { + is_private = true; + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + } + + bool identifier_found = false; + + if (context_p->token.type == LEXER_LITERAL && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type) + && lexer_compare_literal_to_string (context_p, "constructor", 11) + && stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR) + { + parser_stack_pop_uint8 (context_p); + scanner_class_info_t *private_members_p; + parser_stack_pop (context_p, &private_members_p, sizeof (scanner_class_info_t *)); + private_members_p->info.u8_arg = SCANNER_CONSTRUCTOR_EXPLICIT; + parser_stack_push (context_p, &private_members_p, sizeof (scanner_class_info_t *)); + parser_stack_push_uint8 (context_p, SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR); + } + else if (lexer_token_is_identifier (context_p, "static", 6)) + { + scanner_source_start_t static_start; + static_start.source_p = context_p->source_p - 1; + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + private_field_flags = (scanner_private_field_flags_t) ((unsigned int) private_field_flags | (unsigned int) SCANNER_PRIVATE_FIELD_STATIC); + + if (!is_private && context_p->token.type == LEXER_LEFT_BRACE) + { + parser_stack_push (context_p, &static_start, sizeof (scanner_source_start_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATIC_BLOCK); + + scanner_literal_pool_t *literal_pool_p = + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + literal_pool_p->source_p = context_p->source_p - 1; + + lexer_next_token (context_p); + + scanner_context.mode = SCAN_MODE_STATEMENT_OR_TERMINATOR; + + continue; + } + } + + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + + uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION; + + private_field_flags = ((bool)private_field_flags || lexer_token_is_identifier (context_p, "get", 3) ? SCANNER_PRIVATE_FIELD_GETTER : (scanner_private_field_flags_t) 0); + private_field_flags = ((bool)private_field_flags || lexer_token_is_identifier (context_p, "set", 3) ? SCANNER_PRIVATE_FIELD_SETTER : (scanner_private_field_flags_t) 0); + + if (private_field_flags & SCANNER_PRIVATE_FIELD_GETTER_SETTER) + { + private_field_flags = (scanner_private_field_flags_t) ((uint32_t) private_field_flags & ~(uint32_t) SCANNER_PRIVATE_FIELD_PROPERTY); + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (is_private) + { + private_field_flags = (scanner_private_field_flags_t) ((int) private_field_flags | (int) SCANNER_PRIVATE_FIELD_METHOD); + scanner_add_private_identifier (context_p, private_field_flags); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + continue; + } + } + else if (lexer_token_is_identifier (context_p, "async", 5)) + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + + if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (is_private) + { + private_field_flags = (scanner_private_field_flags_t) ((int) private_field_flags | (int) SCANNER_PRIVATE_FIELD_METHOD); + scanner_add_private_identifier (context_p, private_field_flags); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + continue; + } + + literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC; + + if (context_p->token.type == LEXER_MULTIPLY) + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + } + } + else if (context_p->token.type == LEXER_MULTIPLY) + { + if (is_private) + { + scanner_raise_error (context_p); + } + + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + if (is_private) + { + scanner_raise_error (context_p); + } + + if (literal_pool_flags != SCANNER_LITERAL_POOL_FUNCTION) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + } + + parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags)); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + if (context_p->token.type == LEXER_HASHMARK) + { + if (is_private) + { + scanner_raise_error (context_p); + } + + is_private = true; + context_p->token.flags |= LEXER_NO_SKIP_SPACES; + lexer_next_token (context_p); + } + + if (is_private) + { + if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)) + { + private_field_flags = (scanner_private_field_flags_t) ((int) private_field_flags | (int) SCANNER_PRIVATE_FIELD_METHOD); + } + + scanner_add_private_identifier (context_p, private_field_flags); + } + + if (context_p->token.type == LEXER_LITERAL) + { + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + identifier_found = true; + } + + if (!identifier_found) + { + scanner_raise_error (context_p); + } + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION; + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags); + continue; + } + + if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR) + { + scanner_raise_error (context_p); + } + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_push_class_field_initializer (context_p, &scanner_context); + break; + } + + if (context_p->token.type == LEXER_SEMICOLON) + { + scanner_context.mode = SCAN_MODE_CLASS_BODY; + continue; + } + + if (context_p->token.type != LEXER_RIGHT_BRACE && !(context_p->token.flags & LEXER_WAS_NEWLINE)) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_CLASS_BODY_NO_SCAN; + continue; + } + case SCAN_MODE_POST_PRIMARY_EXPRESSION: + { + if (scanner_scan_post_primary_expression (context_p, &scanner_context, type, stack_top)) + { + break; + } + type = (lexer_token_type_t) context_p->token.type; + /* FALLTHRU */ + } + case SCAN_MODE_PRIMARY_EXPRESSION_END: + { + if (scanner_scan_primary_expression_end (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN) + { + continue; + } + break; + } + case SCAN_MODE_STATEMENT_OR_TERMINATOR: + { + if (type == LEXER_RIGHT_BRACE || type == LEXER_EOS) + { + scanner_context.mode = SCAN_MODE_STATEMENT_END; + continue; + } + /* FALLTHRU */ + } + case SCAN_MODE_STATEMENT: + { + if (scanner_scan_statement (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN) + { + continue; + } + break; + } + case SCAN_MODE_STATEMENT_END: + { + if (scanner_scan_statement_end (context_p, &scanner_context, type) != SCAN_NEXT_TOKEN) + { + continue; + } + + if (context_p->token.type == LEXER_EOS) + { + goto scan_completed; + } + + break; + } + case SCAN_MODE_VAR_STATEMENT: + { + if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE) + { + uint8_t binding_type = SCANNER_BINDING_VAR; + + if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START) + { + binding_type = SCANNER_BINDING_LET; + } + else if (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START) + { + binding_type = SCANNER_BINDING_CONST; + } + + scanner_push_destructuring_pattern (context_p, &scanner_context, binding_type, false); + + if (type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context.mode = SCAN_MODE_BINDING; + break; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context.mode = SCAN_MODE_PROPERTY_NAME; + continue; + } + + if (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context); + + if (stack_top != SCAN_STACK_VAR && stack_top != SCAN_STACK_FOR_VAR_START) + { + scanner_detect_invalid_let (context_p, literal_p); + + if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START) + { + literal_p->type |= SCANNER_LITERAL_IS_LET; + } + else + { + JERRY_ASSERT (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START); + literal_p->type |= SCANNER_LITERAL_IS_CONST; + } + + lexer_next_token (context_p); + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + } + else if (context_p->token.type == LEXER_ASSIGN) + { + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + } + } + else + { + if (!(literal_p->type & SCANNER_LITERAL_IS_VAR)) + { + scanner_detect_invalid_var (context_p, &scanner_context, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_VAR; + + if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + } + } + + lexer_next_token (context_p); + } + +#if JERRY_MODULE_SYSTEM + if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + } +#endif /* JERRY_MODULE_SYSTEM */ + + switch (context_p->token.type) + { + case LEXER_ASSIGN: + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + /* FALLTHRU */ + } + case LEXER_COMMA: + { + lexer_next_token (context_p); + continue; + } + } + + if (SCANNER_IS_FOR_START (stack_top)) + { +#if JERRY_MODULE_SYSTEM + JERRY_ASSERT (!(scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT)); +#endif /* JERRY_MODULE_SYSTEM */ + + if (context_p->token.type != LEXER_SEMICOLON && context_p->token.type != LEXER_KEYW_IN + && !SCANNER_IDENTIFIER_IS_OF ()) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + continue; + } + + JERRY_ASSERT (stack_top == SCAN_STACK_VAR || stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST); + +#if JERRY_MODULE_SYSTEM + scanner_context.active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT; +#endif /* JERRY_MODULE_SYSTEM */ + + scanner_context.mode = SCAN_MODE_STATEMENT_END; + parser_stack_pop_uint8 (context_p); + continue; + } + case SCAN_MODE_FUNCTION_ARGUMENTS: + { + JERRY_ASSERT (stack_top == SCAN_STACK_SCRIPT_FUNCTION || stack_top == SCAN_STACK_FUNCTION_STATEMENT + || stack_top == SCAN_STACK_FUNCTION_EXPRESSION || stack_top == SCAN_STACK_FUNCTION_PROPERTY); + + scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p; + + JERRY_ASSERT (literal_pool_p != NULL && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)); + + literal_pool_p->source_p = context_p->source_p; + + if (JERRY_UNLIKELY (scanner_context.async_source_p != NULL)) + { + literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ASYNC; + literal_pool_p->source_p = scanner_context.async_source_p; + scanner_context.async_source_p = NULL; + } + + if (type != LEXER_LEFT_PAREN) + { + scanner_raise_error (context_p); + } + lexer_next_token (context_p); + + /* FALLTHRU */ + } + case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS: + { + if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS) + { + lexer_lit_location_t *argument_literal_p; + + do + { + if (context_p->token.type == LEXER_THREE_DOTS) + { + scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT; + lexer_next_token (context_p); + } + + if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE) + { + argument_literal_p = NULL; + break; + } + + if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + + argument_literal_p = scanner_append_argument (context_p, &scanner_context); + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_COMMA) + { + break; + } + + lexer_next_token (context_p); + } while (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS); + + if (argument_literal_p == NULL) + { + scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT; + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS); + scanner_append_hole (context_p, &scanner_context); + scanner_push_destructuring_pattern (context_p, &scanner_context, SCANNER_BINDING_ARG, false); + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + scanner_context.mode = SCAN_MODE_BINDING; + break; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context.mode = SCAN_MODE_PROPERTY_NAME; + continue; + } + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT; + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (argument_literal_p->type & SCANNER_LITERAL_IS_USED) + { + JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE); + break; + } + + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = argument_literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + break; + } + } + + if (context_p->token.type == LEXER_EOS && stack_top == SCAN_STACK_SCRIPT_FUNCTION) + { + /* End of argument parsing. */ + scanner_info_t *scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, sizeof (scanner_info_t)); + scanner_info_p->next_p = context_p->next_scanner_info_p; + scanner_info_p->source_p = NULL; + scanner_info_p->type = SCANNER_TYPE_END_ARGUMENTS; + scanner_context.end_arguments_p = scanner_info_p; + + context_p->next_scanner_info_p = scanner_info_p; + context_p->source_p = context_p->source_start_p; + context_p->source_end_p = context_p->source_start_p + context_p->source_size; + lexer_init_line_info (context_p); + + scanner_filter_arguments (context_p, &scanner_context); + lexer_next_token (context_p); + scanner_check_directives (context_p, &scanner_context); + continue; + } + + if (context_p->token.type != LEXER_RIGHT_PAREN) + { + scanner_raise_error (context_p); + } + + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_LEFT_BRACE) + { + scanner_raise_error (context_p); + } + + scanner_filter_arguments (context_p, &scanner_context); + lexer_next_token (context_p); + scanner_check_directives (context_p, &scanner_context); + continue; + } + case SCAN_MODE_PROPERTY_NAME: + { + JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL); + + if (lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS)) + { + lexer_check_property_modifier (context_p); + } + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_COMPUTED_PROPERTY); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + if (context_p->token.type == LEXER_THREE_DOTS) + { + *parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_REST; + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context.binding_type != SCANNER_BINDING_NONE) + { + scanner_context.mode = SCAN_MODE_BINDING; + } + break; + } + + if (context_p->token.type == LEXER_RIGHT_BRACE) + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + continue; + } + + if (context_p->token.type == LEXER_PROPERTY_GETTER || context_p->token.type == LEXER_KEYW_ASYNC + || context_p->token.type == LEXER_MULTIPLY || context_p->token.type == LEXER_PROPERTY_SETTER) + { + uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION; + + if (context_p->token.type == LEXER_MULTIPLY) + { + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + else if (context_p->token.type == LEXER_KEYW_ASYNC) + { + literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC; + + if (lexer_consume_generator (context_p)) + { + literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR; + } + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS); + + if (context_p->token.type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags)); + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + if (context_p->token.type != LEXER_LITERAL) + { + scanner_raise_error (context_p); + } + + scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags); + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + break; + } + + if (context_p->token.type != LEXER_LITERAL) + { + scanner_raise_error (context_p); + } + + parser_line_counter_t start_line = context_p->token.line; + parser_line_counter_t start_column = context_p->token.column; + bool is_ident = (context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_PAREN) + { + scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION); + + parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY); + scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; + continue; + } + + if (is_ident + && (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_BRACE + || context_p->token.type == LEXER_ASSIGN)) + { + context_p->source_p = context_p->token.lit_location.char_p; + context_p->line = start_line; + context_p->column = start_column; + + lexer_next_token (context_p); + + JERRY_ASSERT (context_p->token.type != LEXER_LITERAL + || context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + if (context_p->token.type != LEXER_LITERAL) + { + scanner_raise_error (context_p); + } + + if (scanner_context.binding_type != SCANNER_BINDING_NONE) + { + scanner_context.mode = SCAN_MODE_BINDING; + continue; + } + + scanner_add_reference (context_p, &scanner_context); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_ASSIGN) + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END; + continue; + } + + if (context_p->token.type != LEXER_COLON) + { + scanner_raise_error (context_p); + } + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + + if (scanner_context.binding_type != SCANNER_BINDING_NONE) + { + scanner_context.mode = SCAN_MODE_BINDING; + } + break; + } + case SCAN_MODE_BINDING: + { + JERRY_ASSERT (scanner_context.binding_type == SCANNER_BINDING_VAR + || scanner_context.binding_type == SCANNER_BINDING_LET + || scanner_context.binding_type == SCANNER_BINDING_CATCH + || scanner_context.binding_type == SCANNER_BINDING_CONST + || scanner_context.binding_type == SCANNER_BINDING_ARG + || scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG); + + if (type == LEXER_THREE_DOTS) + { + lexer_next_token (context_p); + type = (lexer_token_type_t) context_p->token.type; + } + + if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE) + { + scanner_push_destructuring_pattern (context_p, &scanner_context, scanner_context.binding_type, true); + + if (type == LEXER_LEFT_SQUARE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL); + break; + } + + parser_stack_push_uint8 (context_p, 0); + parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL); + scanner_context.mode = SCAN_MODE_PROPERTY_NAME; + continue; + } + + if (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + continue; + } + + lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context); + + scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + + if (scanner_context.binding_type == SCANNER_BINDING_VAR) + { + if (!(literal_p->type & SCANNER_LITERAL_IS_VAR)) + { + scanner_detect_invalid_var (context_p, &scanner_context, literal_p); + literal_p->type |= SCANNER_LITERAL_IS_VAR; + + if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH) + { + literal_p->type |= SCANNER_LITERAL_NO_REG; + } + } + break; + } + + if (scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG) + { + literal_p->type |= SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + break; + } + } + else + { + scanner_detect_invalid_let (context_p, literal_p); + + if (scanner_context.binding_type <= SCANNER_BINDING_CATCH) + { + JERRY_ASSERT ((scanner_context.binding_type == SCANNER_BINDING_LET) + || (scanner_context.binding_type == SCANNER_BINDING_CATCH)); + + literal_p->type |= SCANNER_LITERAL_IS_LET; + } + else + { + literal_p->type |= SCANNER_LITERAL_IS_CONST; + + if (scanner_context.binding_type == SCANNER_BINDING_ARG) + { + literal_p->type |= SCANNER_LITERAL_IS_ARG; + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + break; + } + } + } + + if (literal_p->type & SCANNER_LITERAL_IS_USED) + { + literal_p->type |= SCANNER_LITERAL_EARLY_CREATE; + break; + } + } + + scanner_binding_item_t *binding_item_p; + binding_item_p = (scanner_binding_item_t *) scanner_malloc (context_p, sizeof (scanner_binding_item_t)); + + binding_item_p->next_p = scanner_context.active_binding_list_p->items_p; + binding_item_p->literal_p = literal_p; + + scanner_context.active_binding_list_p->items_p = binding_item_p; + + lexer_next_token (context_p); + if (context_p->token.type != LEXER_ASSIGN) + { + continue; + } + + scanner_binding_literal_t binding_literal; + binding_literal.literal_p = literal_p; + + parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t)); + parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT); + + scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION; + break; + } + } + + lexer_next_token (context_p); + } + +scan_completed: + if (context_p->stack_top_uint8 != SCAN_STACK_SCRIPT && context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION) + { + scanner_raise_error (context_p); + } + + scanner_pop_literal_pool (context_p, &scanner_context); + + JERRY_ASSERT (scanner_context.active_binding_list_p == NULL); + JERRY_ASSERT (scanner_context.active_literal_pool_p == NULL); + +#ifndef JERRY_NDEBUG + scanner_context.context_status_flags |= PARSER_SCANNING_SUCCESSFUL; +#endif /* !JERRY_NDEBUG */ + } + PARSER_CATCH + { + while (scanner_context.active_binding_list_p != NULL) + { + scanner_pop_binding_list (&scanner_context); + } + + if (JERRY_UNLIKELY (context_p->error != PARSER_ERR_OUT_OF_MEMORY)) + { + /* Ignore the errors thrown by the lexer. */ + context_p->error = PARSER_ERR_NO_ERROR; + + /* The following code may allocate memory, so it is enclosed in a try/catch. */ + PARSER_TRY (context_p->try_buffer) + { + if (scanner_context.status_flags & SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION) + { + JERRY_ASSERT (scanner_context.async_source_p != NULL); + + scanner_info_t *info_p; + info_p = scanner_insert_info (context_p, scanner_context.async_source_p, sizeof (scanner_info_t)); + info_p->type = SCANNER_TYPE_ERR_ASYNC_FUNCTION; + } + + while (scanner_context.active_literal_pool_p != NULL) + { + scanner_pop_literal_pool (context_p, &scanner_context); + } + } + PARSER_CATCH + { + JERRY_ASSERT (context_p->error == PARSER_ERR_OUT_OF_MEMORY); + } + PARSER_TRY_END + } + + JERRY_ASSERT (context_p->error == PARSER_ERR_NO_ERROR || context_p->error == PARSER_ERR_OUT_OF_MEMORY); + + if (context_p->error == PARSER_ERR_OUT_OF_MEMORY) + { + while (scanner_context.active_literal_pool_p != NULL) + { + scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p; + + scanner_context.active_literal_pool_p = literal_pool_p->prev_p; + + parser_list_free (&literal_pool_p->literal_pool); + scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t)); + } + + parser_stack_free (context_p); + return; + } + } + PARSER_TRY_END + + context_p->status_flags = scanner_context.context_status_flags; + context_p->global_status_flags &= (uint32_t) ~ECMA_PARSE_INTERNAL_PRE_SCANNING; + scanner_reverse_info_list (context_p); + +#if JERRY_PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + scanner_info_t *info_p = context_p->next_scanner_info_p; + const uint8_t *source_start_p = + (context_p->arguments_start_p == NULL ? context_p->source_start_p : context_p->arguments_start_p); + + while (info_p->type != SCANNER_TYPE_END) + { + const char *name_p = NULL; + bool print_location = false; + + switch (info_p->type) + { + case SCANNER_TYPE_END_ARGUMENTS: + { + JERRY_DEBUG_MSG (" END_ARGUMENTS\n"); + source_start_p = context_p->source_start_p; + break; + } + case SCANNER_TYPE_FUNCTION: + case SCANNER_TYPE_BLOCK: + { + const uint8_t *prev_source_p = info_p->source_p - 1; + const uint8_t *data_p; + + if (info_p->type == SCANNER_TYPE_FUNCTION) + { + data_p = (const uint8_t *) (info_p + 1); + + JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d", (int) info_p->u8_arg, (int) info_p->u16_arg); + } + else + { + data_p = (const uint8_t *) (info_p + 1); + + JERRY_DEBUG_MSG (" BLOCK:"); + } + + JERRY_DEBUG_MSG (" source:%d\n", (int) (info_p->source_p - source_start_p)); + + while (data_p[0] != SCANNER_STREAM_TYPE_END) + { + switch (data_p[0] & SCANNER_STREAM_TYPE_MASK) + { + case SCANNER_STREAM_TYPE_HOLE: + { + JERRY_DEBUG_MSG (" HOLE\n"); + data_p++; + continue; + } + case SCANNER_STREAM_TYPE_ARGUMENTS: + { + JERRY_DEBUG_MSG (" ARGUMENTS%s%s\n", + (data_p[0] & SCANNER_STREAM_NO_REG) ? " *" : "", + (data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) ? " L" : ""); + data_p++; + continue; + } + case SCANNER_STREAM_TYPE_ARGUMENTS_FUNC: + { + JERRY_DEBUG_MSG (" ARGUMENTS_FUNC%s%s\n", + (data_p[0] & SCANNER_STREAM_NO_REG) ? " *" : "", + (data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) ? " L" : ""); + data_p++; + continue; + } + case SCANNER_STREAM_TYPE_VAR: + { + JERRY_DEBUG_MSG (" VAR "); + break; + } + case SCANNER_STREAM_TYPE_LET: + { + JERRY_DEBUG_MSG (" LET "); + break; + } + case SCANNER_STREAM_TYPE_CONST: + { + JERRY_DEBUG_MSG (" CONST "); + break; + } + case SCANNER_STREAM_TYPE_LOCAL: + { + JERRY_DEBUG_MSG (" LOCAL "); + break; + } +#if JERRY_MODULE_SYSTEM + case SCANNER_STREAM_TYPE_IMPORT: + { + JERRY_DEBUG_MSG (" IMPORT "); + break; + } +#endif /* JERRY_MODULE_SYSTEM */ + case SCANNER_STREAM_TYPE_ARG: + { + JERRY_DEBUG_MSG (" ARG "); + break; + } + case SCANNER_STREAM_TYPE_ARG_VAR: + { + JERRY_DEBUG_MSG (" ARG_VAR "); + break; + } + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: + { + JERRY_DEBUG_MSG (" DESTRUCTURED_ARG "); + break; + } + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR: + { + JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_VAR "); + break; + } + case SCANNER_STREAM_TYPE_ARG_FUNC: + { + JERRY_DEBUG_MSG (" ARG_FUNC "); + break; + } + case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + { + JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_FUNC "); + break; + } + case SCANNER_STREAM_TYPE_FUNC: + { + JERRY_DEBUG_MSG (" FUNC "); + break; + } + default: + { + JERRY_UNREACHABLE (); + data_p++; + continue; + } + } + + size_t length; + + if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) + { + if (data_p[2] != 0) + { + prev_source_p += data_p[2]; + length = 2 + 1; + } + else + { + memcpy (&prev_source_p, data_p + 2 + 1, sizeof (uintptr_t)); + length = 2 + 1 + sizeof (uintptr_t); + } + } + else + { + int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8; + + if (diff <= UINT8_MAX) + { + diff = -diff; + } + + prev_source_p += diff; + length = 2 + 2; + } + + if (data_p[0] & SCANNER_STREAM_EARLY_CREATE) + { + JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG); + JERRY_DEBUG_MSG ("*"); + } + + if (data_p[0] & SCANNER_STREAM_NO_REG) + { + JERRY_DEBUG_MSG ("* "); + } + + JERRY_DEBUG_MSG ("'%.*s'\n", data_p[1], (char *) prev_source_p); + prev_source_p += data_p[1]; + data_p += length; + } + break; + } + case SCANNER_TYPE_WHILE: + { + name_p = "WHILE"; + print_location = true; + break; + } + case SCANNER_TYPE_FOR: + { + scanner_for_info_t *for_info_p = (scanner_for_info_t *) info_p; + JERRY_DEBUG_MSG (" FOR: source:%d expression:%d[%d:%d] end:%d[%d:%d]\n", + (int) (for_info_p->info.source_p - source_start_p), + (int) (for_info_p->expression_location.source_p - source_start_p), + (int) for_info_p->expression_location.line, + (int) for_info_p->expression_location.column, + (int) (for_info_p->end_location.source_p - source_start_p), + (int) for_info_p->end_location.line, + (int) for_info_p->end_location.column); + break; + } + case SCANNER_TYPE_FOR_IN: + { + name_p = "FOR-IN"; + print_location = true; + break; + } + case SCANNER_TYPE_FOR_OF: + { + name_p = "FOR-OF"; + print_location = true; + break; + } + case SCANNER_TYPE_SWITCH: + { + JERRY_DEBUG_MSG (" SWITCH: source:%d\n", (int) (info_p->source_p - source_start_p)); + + scanner_case_info_t *current_case_p = ((scanner_switch_info_t *) info_p)->case_p; + + while (current_case_p != NULL) + { + JERRY_DEBUG_MSG (" CASE: location:%d[%d:%d]\n", + (int) (current_case_p->location.source_p - source_start_p), + (int) current_case_p->location.line, + (int) current_case_p->location.column); + + current_case_p = current_case_p->next_p; + } + break; + } + case SCANNER_TYPE_CASE: + { + name_p = "CASE"; + print_location = true; + break; + } + case SCANNER_TYPE_INITIALIZER: + { + scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p; + JERRY_DEBUG_MSG (" INITIALIZER: flags: 0x%x source:%d location:%d[%d:%d]\n", + (int) info_p->u8_arg, + (int) (location_info_p->info.source_p - source_start_p), + (int) (location_info_p->location.source_p - source_start_p), + (int) location_info_p->location.line, + (int) location_info_p->location.column); + break; + } + case SCANNER_TYPE_CLASS_CONSTRUCTOR: + { + JERRY_DEBUG_MSG (" CLASS: source:%d\n", (int) (info_p->source_p - source_start_p)); + print_location = false; + break; + } + case SCANNER_TYPE_CLASS_STATIC_BLOCK_END: + { + name_p = "SCANNER_TYPE_CLASS_STATIC_BLOCK_END"; + print_location = true; + break; + } + case SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END: + { + name_p = "SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END"; + print_location = true; + break; + } + case SCANNER_TYPE_LET_EXPRESSION: + { + JERRY_DEBUG_MSG (" LET_EXPRESSION: source:%d\n", (int) (info_p->source_p - source_start_p)); + break; + } + case SCANNER_TYPE_ERR_REDECLARED: + { + JERRY_DEBUG_MSG (" JERRY_FATAL_REDECLARED: source:%d\n", (int) (info_p->source_p - source_start_p)); + break; + } + case SCANNER_TYPE_ERR_ASYNC_FUNCTION: + { + JERRY_DEBUG_MSG (" JERRY_FATAL_ASYNC_FUNCTION: source:%d\n", (int) (info_p->source_p - source_start_p)); + break; + } + case SCANNER_TYPE_LITERAL_FLAGS: + { + JERRY_DEBUG_MSG (" SCANNER_TYPE_LITERAL_FLAGS: flags: 0x%x source:%d\n", + (int) info_p->u8_arg, + (int) (info_p->source_p - source_start_p)); + print_location = false; + break; + } + case SCANNER_TYPE_EXPORT_MODULE_SPECIFIER: + { + JERRY_DEBUG_MSG (" EXPORT_WITH_MODULE_SPECIFIER: source:%d\n", (int) (info_p->source_p - source_start_p)); + print_location = false; + break; + } + } + + if (print_location) + { + scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p; + JERRY_DEBUG_MSG (" %s: source:%d location:%d[%d:%d]\n", + name_p, + (int) (location_info_p->info.source_p - source_start_p), + (int) (location_info_p->location.source_p - source_start_p), + (int) location_info_p->location.line, + (int) location_info_p->location.column); + } + + info_p = info_p->next_p; + } + + JERRY_DEBUG_MSG ("\n--- Scanning end ---\n\n"); + } +#endif /* JERRY_PARSER_DUMP_BYTE_CODE */ + + parser_stack_free (context_p); +} /* scanner_scan_all */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.h new file mode 100644 index 00000000..78655685 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/js-scanner.h @@ -0,0 +1,303 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_SCANNER_H +#define JS_SCANNER_H + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup jsparser JavaScript + * @{ + * + * \addtogroup jsparser_scanner Scanner + * @{ + */ + +/** + * Allowed types for scanner_info_t structures. + */ +typedef enum +{ + SCANNER_TYPE_END, /**< mark the last info block */ + SCANNER_TYPE_END_ARGUMENTS, /**< mark the end of function arguments + * (only present if a function script is parsed) */ + SCANNER_TYPE_FUNCTION, /**< declarations in a function */ + SCANNER_TYPE_BLOCK, /**< declarations in a code block (usually enclosed in {}) */ + SCANNER_TYPE_WHILE, /**< while statement */ + SCANNER_TYPE_FOR, /**< for statement */ + SCANNER_TYPE_FOR_IN, /**< for-in statement */ + SCANNER_TYPE_FOR_OF, /**< for-of statement */ + SCANNER_TYPE_SWITCH, /**< switch statement */ + SCANNER_TYPE_CASE, /**< case statement */ + SCANNER_TYPE_INITIALIZER, /**< destructuring binding or assignment pattern with initializer */ + SCANNER_TYPE_LITERAL_FLAGS, /**< object or array literal with non-zero flags (stored in u8_arg) */ + SCANNER_TYPE_CLASS_CONSTRUCTOR, /**< class constructor */ + SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END, /**< class field initializer end */ + SCANNER_TYPE_CLASS_STATIC_BLOCK_END, /**< class static block end */ + SCANNER_TYPE_LET_EXPRESSION, /**< let expression */ + SCANNER_TYPE_ERR_REDECLARED, /**< syntax error: a variable is redeclared */ + SCANNER_TYPE_ERR_ASYNC_FUNCTION, /**< an invalid async function follows */ + SCANNER_TYPE_EXPORT_MODULE_SPECIFIER, /**< export with module specifier */ +} scanner_info_type_t; + +/** + * Source code location which can be used to change the position of parsing. + */ +typedef struct +{ + const uint8_t *source_p; /**< next source byte */ + parser_line_counter_t line; /**< token start line */ + parser_line_counter_t column; /**< token start column */ +} scanner_location_t; + +/** + * Source code range with its start and end position. + */ +typedef struct +{ + const uint8_t *source_end_p; /**< end position */ + scanner_location_t start_location; /**< start location */ +} scanner_range_t; + +/** + * Scanner info blocks which provides information for the parser. + */ +typedef struct scanner_info_t +{ + struct scanner_info_t *next_p; /**< next info structure */ + const uint8_t *source_p; /**< triggering position of this scanner info */ + uint8_t type; /**< type of the scanner info */ + uint8_t u8_arg; /**< custom 8-bit value */ + uint16_t u16_arg; /**< custom 16-bit value */ +} scanner_info_t; + +/** + * Scanner info for class private field + */ +typedef struct scanner_class_private_member_t +{ + lexer_lit_location_t loc; /**< loc */ + uint8_t u8_arg; /**< custom 8-bit value */ + struct scanner_class_private_member_t *prev_p; /**< prev private field */ +} scanner_class_private_member_t; + +/** + * Scanner info extended with class private fields. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_class_private_member_t *members; /**< first private field */ +} scanner_class_info_t; + +/** + * Scanner info extended with a location. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_location_t location; /**< location */ +} scanner_location_info_t; + +/** + * Scanner info for "for" statements. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_location_t expression_location; /**< location of expression start */ + scanner_location_t end_location; /**< location of expression end */ +} scanner_for_info_t; + +/** + * Case statement list for scanner_switch_info_t structure. + */ +typedef struct scanner_case_info_t +{ + struct scanner_case_info_t *next_p; /**< next case statement info */ + scanner_location_t location; /**< location of case statement */ +} scanner_case_info_t; + +/** + * Scanner info for "switch" statements. + */ +typedef struct +{ + scanner_info_t info; /**< header */ + scanner_case_info_t *case_p; /**< list of switch cases */ +} scanner_switch_info_t; + +/* + * Description of compressed streams. + * + * The stream is a sequence of commands which encoded as bytes. The first byte + * contains the type of the command (see scanner_function_compressed_stream_types_t). + * + * The variable declaration commands has two arguments: + * - The first represents the length of the declared identifier + * - The second contains the relative distance from the end of the previous declaration + * Usually the distance is between 1 and 255, and represented as a single byte + * Distances between -256 and 65535 are encoded as two bytes + * Larger distances are encoded as pointers + */ + +/** + * Constants for compressed streams. + */ +typedef enum +{ + SCANNER_STREAM_UINT16_DIFF = (1 << 7), /**< relative distance is between -256 and 65535 */ + SCANNER_STREAM_HAS_ESCAPE = (1 << 6), /**< binding has escape */ + SCANNER_STREAM_NO_REG = (1 << 5), /**< binding cannot be stored in register */ + SCANNER_STREAM_EARLY_CREATE = (1 << 4), /**< binding must be created with ECMA_VALUE_UNINITIALIZED */ + SCANNER_STREAM_LOCAL_ARGUMENTS = SCANNER_STREAM_EARLY_CREATE, /**< arguments is redeclared + * as let/const binding later */ + /* Update SCANNER_STREAM_TYPE_MASK macro if more bits are added. */ +} scanner_compressed_stream_flags_t; + +/** + * Types for compressed streams. + */ +typedef enum +{ + SCANNER_STREAM_TYPE_END, /**< end of scanner data */ + SCANNER_STREAM_TYPE_HOLE, /**< no name is assigned to this argument */ + SCANNER_STREAM_TYPE_ARGUMENTS, /**< arguments object should be created */ + SCANNER_STREAM_TYPE_ARGUMENTS_FUNC, /**< arguments object should be created which + * is later initialized with a function */ + SCANNER_STREAM_TYPE_VAR, /**< var declaration */ + SCANNER_STREAM_TYPE_LET, /**< let declaration */ + SCANNER_STREAM_TYPE_CONST, /**< const declaration */ + SCANNER_STREAM_TYPE_LOCAL, /**< local declaration (e.g. catch block) */ +#if JERRY_MODULE_SYSTEM + SCANNER_STREAM_TYPE_IMPORT, /**< module import */ +#endif /* JERRY_MODULE_SYSTEM */ + /* The next four types must be in this order (see SCANNER_STREAM_TYPE_IS_ARG). */ + SCANNER_STREAM_TYPE_ARG, /**< argument declaration */ + SCANNER_STREAM_TYPE_ARG_VAR, /**< argument declaration which is later copied + * into a variable declared by var statement */ + SCANNER_STREAM_TYPE_DESTRUCTURED_ARG, /**< destructuring argument declaration */ + SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR, /**< destructuring argument declaration which is later + * copied into a variable declared by var statement */ + /* Function types should be at the end. See the SCANNER_STREAM_TYPE_IS_FUNCTION macro. */ + SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which + * is later initialized with a function */ + SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC, /**< destructuring argument declaration which + * is later initialized with a function */ + SCANNER_STREAM_TYPE_FUNC, /**< function declaration */ +} scanner_compressed_stream_types_t; + +/** + * Mask for decoding the type from the compressed stream. + */ +#define SCANNER_STREAM_TYPE_MASK 0xf + +/** + * Checks whether the decoded type represents a function declaration. + */ +#define SCANNER_STREAM_TYPE_IS_FUNCTION(type) ((type) >= SCANNER_STREAM_TYPE_ARG_FUNC) + +/** + * Checks whether the decoded type represents a function argument. + */ +#define SCANNER_STREAM_TYPE_IS_ARG(type) \ + ((type) >= SCANNER_STREAM_TYPE_ARG && (type) <= SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR) + +/** + * Checks whether the decoded type represents both a function argument and a function declaration. + */ +#define SCANNER_STREAM_TYPE_IS_ARG_FUNC(type) \ + ((type) == SCANNER_STREAM_TYPE_ARG_FUNC || (type) == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC) + +/** + * Checks whether the decoded type represents an arguments declaration + */ +#define SCANNER_STREAM_TYPE_IS_ARGUMENTS(type) \ + ((type) == SCANNER_STREAM_TYPE_ARGUMENTS || (type) == SCANNER_STREAM_TYPE_ARGUMENTS_FUNC) + +/** + * Constants for u8_arg flags in scanner_function_info_t. + */ +typedef enum +{ + SCANNER_FUNCTION_ARGUMENTS_NEEDED = (1 << 0), /**< arguments object needs to be created */ + SCANNER_FUNCTION_HAS_COMPLEX_ARGUMENT = (1 << 1), /**< function has complex (ES2015+) argument definition */ + SCANNER_FUNCTION_LEXICAL_ENV_NEEDED = (1 << 2), /**< lexical environment is needed for the function body */ + SCANNER_FUNCTION_STATEMENT = (1 << 3), /**< function is function statement (not arrow expression) + * this flag must be combined with the type of function (e.g. async) */ + SCANNER_FUNCTION_ASYNC = (1 << 4), /**< function is async function */ + SCANNER_FUNCTION_IS_STRICT = (1 << 5), /**< function is strict */ +} scanner_function_flags_t; + +/** + * Constants for u8_arg flags in scanner_class_info_t. + */ +typedef enum +{ + SCANNER_CONSTRUCTOR_IMPLICIT = 0, /**< implicit constructor */ + SCANNER_CONSTRUCTOR_EXPLICIT = (1 << 0), /**< explicit constructor */ + SCANNER_SUCCESSFUL_CLASS_SCAN = (1 << 1), /**< class scan was successful */ + SCANNER_PRIVATE_FIELD_ACTIVE = (1 << 2), /**< private field is active */ +} scanner_constuctor_flags_t; + +/** + * Constants for u8_arg flags in scanner_class_private_member_t. + */ +typedef enum +{ + SCANNER_PRIVATE_FIELD_PROPERTY = (1 << 0), /**< private field initializer */ + SCANNER_PRIVATE_FIELD_METHOD = (1 << 1), /**< private field method */ + SCANNER_PRIVATE_FIELD_STATIC = (1 << 2), /**< static private property */ + SCANNER_PRIVATE_FIELD_GETTER = (1 << 3), /**< private field getter */ + SCANNER_PRIVATE_FIELD_SETTER = (1 << 4), /**< private field setter */ + SCANNER_PRIVATE_FIELD_SEEN = (1 << 5), /**< private field has already been seen */ + SCANNER_PRIVATE_FIELD_IGNORED = SCANNER_PRIVATE_FIELD_METHOD | SCANNER_PRIVATE_FIELD_STATIC, + SCANNER_PRIVATE_FIELD_GETTER_SETTER = (SCANNER_PRIVATE_FIELD_GETTER | SCANNER_PRIVATE_FIELD_SETTER), + SCANNER_PRIVATE_FIELD_PROPERTY_GETTER_SETTER = (SCANNER_PRIVATE_FIELD_PROPERTY | SCANNER_PRIVATE_FIELD_GETTER_SETTER), +} scanner_private_field_flags_t; + +/** + * Object or array literal constants for u8_arg flags in scanner_info_t. + */ +typedef enum +{ + /* These flags affects both array and object literals */ + SCANNER_LITERAL_DESTRUCTURING_FOR = (1 << 0), /**< for loop with destructuring pattern */ + SCANNER_LITERAL_NO_DESTRUCTURING = (1 << 1), /**< this literal cannot be a destructuring pattern */ + /* These flags affects only object literals */ + SCANNER_LITERAL_OBJECT_HAS_SUPER = (1 << 2), /**< super keyword is used in the object literal */ + SCANNER_LITERAL_OBJECT_HAS_REST = (1 << 3), /**< the object literal has a member prefixed with three dots */ +} scanner_literal_flags_t; + +/** + * Option bits for scanner_create_variables function. + */ +typedef enum +{ + SCANNER_CREATE_VARS_NO_OPTS = 0, /**< no options */ + SCANNER_CREATE_VARS_IS_SCRIPT = (1 << 0), /**< create variables for script or direct eval */ + SCANNER_CREATE_VARS_IS_MODULE = (1 << 1), /**< create variables for module */ + SCANNER_CREATE_VARS_IS_FUNCTION_ARGS = (1 << 2), /**< create variables for function arguments */ + SCANNER_CREATE_VARS_IS_FUNCTION_BODY = (1 << 3), /**< create variables for function body */ +} scanner_create_variables_flags_t; + +/** + * @} + * @} + * @} + */ + +#endif /* !JS_SCANNER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/meson.build b/src/loaders/lottie/jerryscript/jerry-core/parser/js/meson.build new file mode 100644 index 00000000..f3fc672e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/meson.build @@ -0,0 +1,33 @@ +source_file = [ + 'byte-code.h', + 'common.h', + 'js-lexer.h', + 'js-parser-limits.h', + 'js-parser.h', + 'js-scanner.h', + 'js-parser-internal.h', + 'js-parser-tagged-template-literal.h', + 'js-scanner-internal.h', + 'parser-errors.h', + 'parser-error-messages.inc.h', + 'byte-code.cpp', + 'common.cpp', + 'js-lexer.cpp', + 'js-parser.cpp', + 'js-parser-expr.cpp', + 'js-parser-line-info-create.cpp', + 'js-parser-mem.cpp', + 'js-parser-module.cpp', + 'js-parser-statm.cpp', + 'js-parser-tagged-template-literal.cpp', + 'js-parser-util.cpp', + 'js-scanner.cpp', + 'js-scanner-ops.cpp', + 'js-scanner-util.cpp', + 'parser-errors.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-error-messages.inc.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-error-messages.inc.h new file mode 100644 index 00000000..cfb96494 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-error-messages.inc.h @@ -0,0 +1,233 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by the gen-strings.py script + * from parser-error-messages.ini. Do not edit! */ + +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_LABEL, "Duplicated label") +PARSER_ERROR_DEF (PARSER_ERR_LEFT_PAREN_EXPECTED, "Expected '(' token") +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_PAREN_EXPECTED, "Expected ')' token") +PARSER_ERROR_DEF (PARSER_ERR_COLON_EXPECTED, "Expected ':' token") +PARSER_ERROR_DEF (PARSER_ERR_SEMICOLON_EXPECTED, "Expected ';' token") +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_SQUARE_EXPECTED, "Expected ']' token") +PARSER_ERROR_DEF (PARSER_ERR_LEFT_BRACE_EXPECTED, "Expected '{' token") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM || JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_BRACE_EXPECTED, "Expected '}' token") +#endif /* JERRY_MODULE_SYSTEM \ +|| JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_NUMBER_TOO_LONG, "Number is too long") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_REGEXP_TOO_LONG, "Regexp is too long") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_STATEMENT_EXPECTED, "Statement expected") +PARSER_ERROR_DEF (PARSER_ERR_STRING_TOO_LONG, "String is too long") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_AS_EXPECTED, "Expected 'as' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IN_EXPECTED, "Expected 'in' token") +PARSER_ERROR_DEF (PARSER_ERR_OF_EXPECTED, "Expected 'of' token") +PARSER_ERROR_DEF (PARSER_ERR_EXPRESSION_EXPECTED, "Expression expected") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM || JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IDENTIFIER_EXPECTED, "Identifier expected") +#endif /* JERRY_MODULE_SYSTEM \ +|| JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_OCTAL_DIGIT, "Invalid octal digit") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_SWITCH, "Invalid switch body") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNKNOWN_REGEXP_FLAG, "Unknown regexp flag") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BIN_DIGIT, "Invalid binary digit") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_RIGHT_SQUARE, "Unexpected '}' token") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_FROM_EXPECTED, "Expected 'from' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_MISSING_EXPONENT, "Missing exponent part") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_REGEXP_FLAG, "Duplicated regexp flag") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENT_LIST_EXPECTED, "Expected argument list") +PARSER_ERROR_DEF (PARSER_ERR_IDENTIFIER_TOO_LONG, "Identifier is too long") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_META_EXPECTED, "Expected 'meta' keyword") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNEXPECTED_END, "Unexpected end of input") +PARSER_ERROR_DEF (PARSER_ERR_UNEXPECTED_PRIVATE_FIELD, "Unexpected private field") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED, "Expected '{' or '*' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED, "Expected '}' or ',' token") +PARSER_ERROR_DEF (PARSER_ERR_STRING_EXPECTED, "Expected a string literal") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_HEX_DIGIT, "Invalid hexadecimal digit") +#endif /* JERRY_PARSER */ +#if JERRY_BUILTIN_REGEXP && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNTERMINATED_REGEXP, "Unterminated regexp literal") +#endif /* JERRY_BUILTIN_REGEXP && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_UNTERMINATED_STRING, "Unterminated string literal") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_FROM_COMMA_EXPECTED, "Expected 'from' or ',' token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_EXPORT_NOT_DEFINED, "Export not defined in module") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_MODULE_SYSTEM || JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_VARIABLE_REDECLARED, "Local variable is redeclared") +#endif /* JERRY_MODULE_SYSTEM \ +|| JERRY_PARSER */ +#if JERRY_BUILTIN_BIGINT && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BIGINT, "Number is not a valid BigInt") +#endif /* JERRY_BUILTIN_BIGINT && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED, "Property identifier expected") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER, "Duplicate exported identifier") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_NEW_TARGET_EXPECTED, "Expected new.target expression") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CHARACTER, "Invalid (unexpected) character") +PARSER_ERROR_DEF (PARSER_ERR_NON_STRICT_ARG_DEFINITION, "Non-strict argument definition") +PARSER_ERROR_DEF (PARSER_ERR_UNTERMINATED_MULTILINE_COMMENT, "Unterminated multiline comment") +PARSER_ERROR_DEF (PARSER_ERR_CATCH_FINALLY_EXPECTED, "Catch or finally block expected") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE, "Invalid unicode escape sequence") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_IMPORT_BINDING, "Duplicated imported binding name") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_WHILE_EXPECTED, "While expected for do-while loop") +PARSER_ERROR_DEF (PARSER_ERR_DELETE_PRIVATE_FIELD, "Private fields can not be deleted") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_FOR_LOOP, "Invalid left-hand-side in for-loop") +PARSER_ERROR_DEF (PARSER_ERR_LEFT_HAND_SIDE_EXP_EXPECTED, "Left-hand-side expression expected") +PARSER_ERROR_DEF (PARSER_ERR_LITERAL_LIMIT_REACHED, "Maximum number of literals reached") +PARSER_ERROR_DEF (PARSER_ERR_STACK_LIMIT_REACHED, "Maximum function stack size reached") +PARSER_ERROR_DEF (PARSER_ERR_AWAIT_NOT_ALLOWED, "Await expression is not allowed here") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED, "Expected '{' or '*' or literal token") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_ASSIGNMENT, "Invalid left-hand side in assignment") +PARSER_ERROR_DEF (PARSER_ERR_SCOPE_STACK_LIMIT_REACHED, "Maximum depth of scope stack reached") +PARSER_ERROR_DEF (PARSER_ERR_UNEXPECTED_SUPER_KEYWORD, "Super is not allowed to be used here") +PARSER_ERROR_DEF (PARSER_ERR_YIELD_NOT_ALLOWED, "Yield expression is not allowed here") +PARSER_ERROR_DEF (PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS, "Multiple constructors are not allowed") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM +PARSER_ERROR_DEF (PARSER_ERR_MODULE_UNEXPECTED, "Unexpected import or export statement") +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IDENTIFIER_AFTER_NUMBER, "Identifier cannot start after a number") +PARSER_ERROR_DEF (PARSER_ERR_MULTIPLE_DEFAULTS_NOT_ALLOWED, "Multiple default cases are not allowed") +PARSER_ERROR_DEF (PARSER_ERR_ARRAY_ITEM_SEPARATOR_EXPECTED, "Expected ',' or ']' after an array item") +PARSER_ERROR_DEF (PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION, "Illegal property in declaration context") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_DESTRUCTURING_PATTERN, "Invalid destructuring assignment target") +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_PRIVATE_FIELD, "Private field has already been declared") +PARSER_ERROR_DEF (PARSER_ERR_NO_ARGUMENTS_EXPECTED, "Property getters must have no arguments") +PARSER_ERROR_DEF (PARSER_ERR_ONE_ARGUMENT_EXPECTED, "Property setters must have one argument") +PARSER_ERROR_DEF (PARSER_ERR_CASE_NOT_IN_SWITCH, "Case statement must be in a switch block") +PARSER_ERROR_DEF (PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR, "Class constructor may not be an accessor") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CONTINUE, "Continue statement must be inside a loop") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IMPORT_META_REQUIRE_MODULE, "Cannot use 'import.meta' outside a module") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_IDENTIFIER_PART, "Character cannot be part of an identifier") +PARSER_ERROR_DEF (PARSER_ERR_EVAL_CANNOT_ASSIGNED, "Eval cannot be assigned to in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_WITH_NOT_ALLOWED, "With statement not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_NEW_TARGET_NOT_ALLOWED, "new.target expression is not allowed here") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_IDENTIFIER_START, "Character cannot be start of an identifier") +PARSER_ERROR_DEF (PARSER_ERR_STRICT_IDENT_NOT_ALLOWED, "Identifier name is reserved in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_NULLISH_COALESCING, "Cannot chain nullish with logical AND or OR") +PARSER_ERROR_DEF (PARSER_ERR_DEFAULT_NOT_IN_SWITCH, "Default statement must be in a switch block") +#endif /* JERRY_PARSER */ +#if JERRY_MODULE_SYSTEM && JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_IMPORT_AFTER_NEW, "Module import call is not allowed after new") +#endif /* JERRY_MODULE_SYSTEM && JERRY_PARSER */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_TOO_MANY_CLASS_FIELDS, "Too many computed class fields are declared") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_KEYWORD, "Escape sequences are not allowed in keywords") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENT_LIMIT_REACHED, "Maximum number of function arguments reached") +PARSER_ERROR_DEF (PARSER_ERR_NEWLINE_NOT_ALLOWED, "Newline is not allowed in strings or regexps") +PARSER_ERROR_DEF (PARSER_ERR_OCTAL_NUMBER_NOT_ALLOWED, "Octal numbers are not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_CLASS_PRIVATE_CONSTRUCTOR, "Class constructor may not be a private method") +PARSER_ERROR_DEF (PARSER_ERR_FOR_AWAIT_NO_OF, "only 'of' form is allowed for for-await loops") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENTS_CANNOT_ASSIGNED, "Arguments cannot be assigned to in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BREAK, "Break statement must be inside a loop or switch") +PARSER_ERROR_DEF (PARSER_ERR_OBJECT_ITEM_SEPARATOR_EXPECTED, "Expected ',' or '}' after a property definition") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_BREAK_LABEL, "Labeled statement targeted by a break not found") +#endif /* JERRY_PARSER */ +#if JERRY_PARSER && !(JERRY_BUILTIN_REGEXP) +PARSER_ERROR_DEF (PARSER_ERR_UNSUPPORTED_REGEXP, "Regexp is not supported in the selected profile") +#endif /* JERRY_PARSER && !(JERRY_BUILTIN_REGEXP) */ +#if JERRY_PARSER +PARSER_ERROR_DEF (PARSER_ERR_INVALID_RETURN, "Return statement must be inside a function body") +PARSER_ERROR_DEF (PARSER_ERR_COLON_FOR_CONDITIONAL_EXPECTED, "Expected ':' token for ?: conditional expression") +PARSER_ERROR_DEF (PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER, "Rest parameter must be the last formal parameter") +PARSER_ERROR_DEF (PARSER_ERR_DELETE_IDENT_NOT_ALLOWED, "Deleting identifier is not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_LABELLED_FUNC_NOT_IN_BLOCK, "Labelled functions are only allowed inside blocks") +PARSER_ERROR_DEF (PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER, "Rest parameter may not have a default initializer") +PARSER_ERROR_DEF (PARSER_ERR_EVAL_NOT_ALLOWED, "Eval is not allowed to be used here in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CONTINUE_LABEL, "Labeled statement targeted by a continue not found") +PARSER_ERROR_DEF (PARSER_ERR_LEXICAL_LET_BINDING, "Let binding cannot appear in let/const declarations") +PARSER_ERROR_DEF (PARSER_ERR_UNDECLARED_PRIVATE_FIELD, "Private field must be declared in an enclosing class") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_PREFIX_OP, "Invalid left-hand side expression in prefix operation") +PARSER_ERROR_DEF (PARSER_ERR_OCTAL_ESCAPE_NOT_ALLOWED, "Octal escape sequences are not allowed in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_SETTER_REST_PARAMETER, "Setter function argument must not be a rest parameter") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENTS_IN_CLASS_FIELD, "In class field declarations 'arguments' is not allowed") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_LHS_POSTFIX_OP, "Invalid left-hand side expression in postfix operation") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_UNDERSCORE_IN_NUMBER, "Invalid use of underscore character in number literals") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_EXPONENTIATION, "Left operand of ** operator cannot be unary expression") +PARSER_ERROR_DEF (PARSER_ERR_MISSING_ASSIGN_AFTER_CONST, "Value assignment is expected after a const declaration") +PARSER_ERROR_DEF (PARSER_ERR_ARGUMENTS_NOT_ALLOWED, "Arguments is not allowed to be used here in strict mode") +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_ARGUMENT_NAMES, "Duplicated function argument names are not allowed here") +PARSER_ERROR_DEF (PARSER_ERR_CLASS_STATIC_PROTOTYPE, "Classes may not have a static property called 'prototype'") +PARSER_ERROR_DEF (PARSER_ERR_INVALID_CLASS_CONSTRUCTOR, "Class constructor may not be a generator or async function") +PARSER_ERROR_DEF (PARSER_ERR_TEMPLATE_STR_OCTAL_ESCAPE, "Octal escape sequences are not allowed in template strings") +PARSER_ERROR_DEF (PARSER_ERR_DUPLICATED_PROTO, "Duplicate __proto__ fields are not allowed in object literals") +PARSER_ERROR_DEF (PARSER_ERR_GENERATOR_IN_SINGLE_STATEMENT_POS, + "Generator function cannot appear in a single-statement context") +PARSER_ERROR_DEF (PARSER_ERR_LEXICAL_SINGLE_STATEMENT, + "Lexical declaration cannot appear in a single-statement context") +PARSER_ERROR_DEF (PARSER_ERR_FOR_IN_OF_DECLARATION, "for in-of loop variable declaration may not have an initializer") +PARSER_ERROR_DEF (PARSER_ERR_FOR_AWAIT_NO_ASYNC, "for-await-of is only allowed inside async functions and generators") +PARSER_ERROR_DEF (PARSER_ERR_USE_STRICT_NOT_ALLOWED, + "The 'use strict' directive is not allowed for functions with non-simple arguments") +PARSER_ERROR_DEF (PARSER_ERR_ASSIGNMENT_EXPECTED, + "Unexpected arrow function or yield expression (parentheses around the expression may help)") +#endif /* JERRY_PARSER */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.cpp new file mode 100644 index 00000000..e21f9b0f --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.cpp @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "parser-errors.h" + +#if JERRY_ERROR_MESSAGES +/** + * Struct to store parser error message with its size. + */ +typedef struct +{ + lit_utf8_byte_t *text; /* Text of parser error message. */ + uint8_t size; /* Size of parser error message. */ +} parser_error_message_t; + +/* Error message texts with size. */ +static parser_error_message_t parser_error_messages[] JERRY_ATTR_CONST_DATA = { + { (lit_utf8_byte_t *) "", 0 }, /* PARSER_ERR_EMPTY */ +/** @cond doxygen_suppress */ +#define PARSER_ERROR_DEF(id, utf8_string) { (lit_utf8_byte_t *) utf8_string, sizeof (utf8_string) - 1 }, +#include "parser-error-messages.inc.h" +#undef PARSER_ERROR_DEF + /** @endcond */ +}; +#endif /* JERRY_ERROR_MESSAGES */ + +/** + * Get specified parser error as zero-terminated string + * + * @return pointer to zero-terminated parser error + */ +const lit_utf8_byte_t * +parser_get_error_utf8 (uint32_t id) /**< parser error id */ +{ + JERRY_ASSERT (id < PARSER_ERR_OUT_OF_MEMORY); + +#if JERRY_ERROR_MESSAGES + return parser_error_messages[id].text; +#else /* !JERRY_ERROR_MESSAGES */ + return NULL; +#endif /* JERRY_ERROR_MESSAGES */ +} /* parser_get_error_utf8 */ + +/** + * Get size of specified parser error + * + * @return size in bytes + */ +lit_utf8_size_t +parser_get_error_size (uint32_t id) /**< parser error id */ +{ + JERRY_ASSERT (id < PARSER_ERR_OUT_OF_MEMORY); + +#if JERRY_ERROR_MESSAGES + return parser_error_messages[id].size; +#else /* !JERRY_ERROR_MESSAGES */ + return 0; +#endif /* JERRY_ERROR_MESSAGES */ +} /* parser_get_error_size */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.h b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.h new file mode 100644 index 00000000..775dee03 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/js/parser-errors.h @@ -0,0 +1,44 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PARSER_ERRORS_H +#define PARSER_ERRORS_H + +#include "lit-globals.h" + +typedef enum +{ + PARSER_ERR_EMPTY, +/** @cond doxygen_suppress */ +#if JERRY_ERROR_MESSAGES +#define PARSER_ERROR_DEF(id, ascii_zt_string) id, +#else /* !JERRY_ERROR_MESSAGES */ +#define PARSER_ERROR_DEF(id, ascii_zt_string) id = PARSER_ERR_EMPTY, +#endif /* JERRY_ERROR_MESSAGES */ +#include "parser-error-messages.inc.h" +#undef PARSER_ERROR_DEF + /** @endcond */ + PARSER_ERR_OUT_OF_MEMORY, + PARSER_ERR_INVALID_REGEXP, +#if (JERRY_STACK_LIMIT != 0) + PARSER_ERR_STACK_OVERFLOW, +#endif /* JERRY_STACK_LIMIT != 0 */ + PARSER_ERR_NO_ERROR, +} parser_error_msg_t; + +const lit_utf8_byte_t* parser_get_error_utf8 (uint32_t id); +lit_utf8_size_t parser_get_error_size (uint32_t id); + +#endif /* !PARSER_ERRORS_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/meson.build b/src/loaders/lottie/jerryscript/jerry-core/parser/meson.build new file mode 100644 index 00000000..f0519b25 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/meson.build @@ -0,0 +1,2 @@ +subdir('js') +subdir('regexp') diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/meson.build b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/meson.build new file mode 100644 index 00000000..2bcc0add --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/meson.build @@ -0,0 +1,15 @@ +source_file = [ + 're-bytecode.h', + 're-compiler-context.h', + 're-compiler.h', + 're-parser.h', + 're-token.h', + 're-bytecode.cpp', + 're-compiler.cpp', + 're-parser.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.cpp new file mode 100644 index 00000000..e9b6141e --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.cpp @@ -0,0 +1,620 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "re-bytecode.h" + +#include "ecma-globals.h" +#include "ecma-regexp-object.h" + +#include "lit-strings.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_bytecode Bytecode + * @{ + */ + +void +re_initialize_regexp_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */ +{ + const size_t initial_size = sizeof (re_compiled_code_t); + re_ctx_p->bytecode_start_p = (uint8_t *) jmem_heap_alloc_block (initial_size); + re_ctx_p->bytecode_size = initial_size; +} /* re_initialize_regexp_bytecode */ + +uint32_t +re_bytecode_size (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */ +{ + return (uint32_t) re_ctx_p->bytecode_size; +} /* re_bytecode_size */ + +/** + * Append a new bytecode to the and of the bytecode container + */ +static uint8_t * +re_bytecode_reserve (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const size_t size) /**< size */ +{ + const size_t old_size = re_ctx_p->bytecode_size; + const size_t new_size = old_size + size; + re_ctx_p->bytecode_start_p = reinterpret_cast(jmem_heap_realloc_block (re_ctx_p->bytecode_start_p, old_size, new_size)); + re_ctx_p->bytecode_size = new_size; + return re_ctx_p->bytecode_start_p + old_size; +} /* re_bytecode_reserve */ + +/** + * Insert a new bytecode to the bytecode container + */ +static uint8_t * +re_bytecode_insert (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const size_t offset, /**< distance from the start of the container */ + const size_t size) /**< size */ +{ + const size_t tail_size = re_ctx_p->bytecode_size - offset; + re_bytecode_reserve (re_ctx_p, size); + + uint8_t *dest_p = re_ctx_p->bytecode_start_p + offset; + memmove (dest_p + size, dest_p, tail_size); + + return dest_p; +} /* re_bytecode_insert */ + +/** + * Append a byte + */ +void +re_append_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint8_t byte) /**< byte value */ +{ + uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, sizeof (uint8_t)); + *dest_p = byte; +} /* re_append_byte */ + +/** + * Insert a byte value + */ +void +re_insert_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< distance from the start of the container */ + const uint8_t byte) /**< byte value */ +{ + uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, sizeof (uint8_t)); + *dest_p = byte; +} /* re_insert_byte */ + +/** + * Get a single byte and icnrease bytecode position. + */ +uint8_t +re_get_byte (const uint8_t **bc_p) /**< pointer to bytecode start */ +{ + return *((*bc_p)++); +} /* re_get_byte */ + +/** + * Append a RegExp opcode + */ +void +re_append_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const re_opcode_t opcode) /**< input opcode */ +{ + re_append_byte (re_ctx_p, (uint8_t) opcode); +} /* re_append_opcode */ + +/** + * Insert a RegExp opcode + */ +void +re_insert_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< distance from the start of the container */ + const re_opcode_t opcode) /**< input opcode */ +{ + re_insert_byte (re_ctx_p, offset, (uint8_t) opcode); +} /* re_insert_opcode */ + +/** + * Get a RegExp opcode and increase the bytecode position + * + * @return current RegExp opcode + */ +re_opcode_t +re_get_opcode (const uint8_t **bc_p) /**< pointer to bytecode start */ +{ + return (re_opcode_t) re_get_byte (bc_p); +} /* re_get_opcode */ + +/** + * Encode 2 byte unsigned integer into the bytecode + */ +static void +re_encode_u16 (uint8_t *dest_p, /**< destination */ + const uint16_t value) /**< value */ +{ + *dest_p++ = (uint8_t) ((value >> 8) & 0xFF); + *dest_p = (uint8_t) (value & 0xFF); +} /* re_encode_u16 */ + +/** + * Encode 4 byte unsigned integer into the bytecode + */ +static void +re_encode_u32 (uint8_t *dest_p, /**< destination */ + const uint32_t value) /**< value */ +{ + *dest_p++ = (uint8_t) ((value >> 24) & 0xFF); + *dest_p++ = (uint8_t) ((value >> 16) & 0xFF); + *dest_p++ = (uint8_t) ((value >> 8) & 0xFF); + *dest_p = (uint8_t) (value & 0xFF); +} /* re_encode_u32 */ + +/** + * Decode 2 byte unsigned integer from bytecode + * + * @return uint16_t value + */ +static uint16_t +re_decode_u16 (const uint8_t *src_p) /**< source */ +{ + uint16_t value = (uint16_t) (((uint16_t) *src_p++) << 8); + value = (uint16_t) (value + *src_p++); + return value; +} /* re_decode_u16 */ + +/** + * Decode 4 byte unsigned integer from bytecode + * + * @return uint32_t value + */ +static uint32_t JERRY_ATTR_NOINLINE +re_decode_u32 (const uint8_t *src_p) /**< source */ +{ + uint32_t value = (uint32_t) (((uint32_t) *src_p++) << 24); + value += (uint32_t) (((uint32_t) *src_p++) << 16); + value += (uint32_t) (((uint32_t) *src_p++) << 8); + value += (uint32_t) (*src_p++); + return value; +} /* re_decode_u32 */ + +/** + * Get the encoded size of an uint32_t value. + * + * @return encoded value size + */ +static inline size_t +re_get_encoded_value_size (uint32_t value) /**< value */ +{ + if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX)) + { + return 1; + } + + return 5; +} /* re_get_encoded_value_size */ + +/* + * Encode a value to the specified position in the bytecode. + */ +static void +re_encode_value (uint8_t *dest_p, /**< position in bytecode */ + const uint32_t value) /**< value */ +{ + if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX)) + { + *dest_p = (uint8_t) value; + return; + } + + *dest_p++ = (uint8_t) (RE_VALUE_4BYTE_MARKER); + re_encode_u32 (dest_p, value); +} /* re_encode_value */ + +/** + * Append a value to the end of the bytecode. + */ +void +re_append_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t value) /**< value */ +{ + const size_t size = re_get_encoded_value_size (value); + uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size); + re_encode_value (dest_p, value); +} /* re_append_value */ + +/** + * Insert a value into the bytecode at a specific offset. + */ +void +re_insert_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< bytecode offset */ + const uint32_t value) /**< value */ +{ + const size_t size = re_get_encoded_value_size (value); + uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size); + re_encode_value (dest_p, value); +} /* re_insert_value */ + +/** + * Read an encoded value from the bytecode. + * + * @return decoded value + */ +uint32_t +re_get_value (const uint8_t **bc_p) /** refence to bytecode pointer */ +{ + uint32_t value = *(*bc_p)++; + if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX)) + { + return value; + } + + value = re_decode_u32 (*bc_p); + *bc_p += sizeof (uint32_t); + return value; +} /* re_get_value */ + +/** + * Append a character to the RegExp bytecode + */ +void +re_append_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const lit_code_point_t cp) /**< code point */ +{ + const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t); + uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size); + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + re_encode_u32 (dest_p, cp); + return; + } + + JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX); + re_encode_u16 (dest_p, (ecma_char_t) cp); +} /* re_append_char */ + +/** + * Append a character to the RegExp bytecode + */ +void +re_insert_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */ + const uint32_t offset, /**< bytecode offset */ + const lit_code_point_t cp) /**< code point*/ +{ + const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t); + + uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size); + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + re_encode_u32 (dest_p, cp); + return; + } + + JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX); + re_encode_u16 (dest_p, (ecma_char_t) cp); +} /* re_insert_char */ + +/** + * Decode a character from the bytecode. + * + * @return decoded character + */ +lit_code_point_t +re_get_char (const uint8_t **bc_p, /**< reference to bytecode pointer */ + bool unicode) /**< full unicode mode */ +{ + lit_code_point_t cp; + + if (unicode) + { + cp = re_decode_u32 (*bc_p); + *bc_p += sizeof (lit_code_point_t); + } + else + { + cp = re_decode_u16 (*bc_p); + *bc_p += sizeof (ecma_char_t); + } + + return cp; +} /* re_get_char */ + +#if JERRY_REGEXP_DUMP_BYTE_CODE +static uint32_t +re_get_bytecode_offset (const uint8_t *start_p, /**< bytecode start pointer */ + const uint8_t *current_p) /**< current bytecode pointer */ +{ + return (uint32_t) ((uintptr_t) current_p - (uintptr_t) start_p); +} /* re_get_bytecode_offset */ + +/** + * RegExp bytecode dumper + */ +void +re_dump_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */ +{ + static const char escape_chars[] = { 'd', 'D', 'w', 'W', 's', 'S' }; + + re_compiled_code_t *compiled_code_p = (re_compiled_code_t *) re_ctx_p->bytecode_start_p; + JERRY_DEBUG_MSG ("Flags: 0x%x ", compiled_code_p->header.status_flags); + JERRY_DEBUG_MSG ("Capturing groups: %d ", compiled_code_p->captures_count); + JERRY_DEBUG_MSG ("Non-capturing groups: %d\n", compiled_code_p->non_captures_count); + + const uint8_t *bytecode_start_p = (const uint8_t *) (compiled_code_p + 1); + const uint8_t *bytecode_p = bytecode_start_p; + + while (true) + { + JERRY_DEBUG_MSG ("[%3u] ", (uint32_t) ((uintptr_t) bytecode_p - (uintptr_t) bytecode_start_p)); + re_opcode_t op = *bytecode_p++; + switch (op) + { + case RE_OP_ALTERNATIVE_START: + { + JERRY_DEBUG_MSG ("ALTERNATIVE_START "); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ALTERNATIVE_NEXT: + { + JERRY_DEBUG_MSG ("ALTERNATIVE_NEXT "); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_NO_ALTERNATIVE: + { + JERRY_DEBUG_MSG ("NO_ALTERNATIVES\n"); + break; + } + case RE_OP_CAPTURING_GROUP_START: + { + JERRY_DEBUG_MSG ("CAPTURING_GROUP_START "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + + const uint32_t qmin = re_get_value (&bytecode_p); + JERRY_DEBUG_MSG ("qmin: %u", qmin); + if (qmin == 0) + { + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset); + } + else + { + JERRY_DEBUG_MSG ("\n"); + } + + break; + } + case RE_OP_NON_CAPTURING_GROUP_START: + { + JERRY_DEBUG_MSG ("NON_CAPTURING_GROUP_START "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + + const uint32_t qmin = re_get_value (&bytecode_p); + JERRY_DEBUG_MSG ("qmin: %u", qmin); + if (qmin == 0) + { + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset); + } + else + { + JERRY_DEBUG_MSG ("\n"); + } + + break; + } + case RE_OP_GREEDY_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("GREEDY_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_LAZY_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("LAZY_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_GREEDY_NON_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("GREEDY_NON_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_LAZY_NON_CAPTURING_GROUP_END: + { + JERRY_DEBUG_MSG ("LAZY_NON_CAPTURING_GROUP_END "); + JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + break; + } + case RE_OP_GREEDY_ITERATOR: + { + JERRY_DEBUG_MSG ("GREEDY_ITERATOR "); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_LAZY_ITERATOR: + { + JERRY_DEBUG_MSG ("LAZY_ITERATOR "); + JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ITERATOR_END: + { + JERRY_DEBUG_MSG ("ITERATOR_END\n"); + break; + } + case RE_OP_BACKREFERENCE: + { + JERRY_DEBUG_MSG ("BACKREFERENCE "); + JERRY_DEBUG_MSG ("idx: %d\n", re_get_value (&bytecode_p)); + break; + } + case RE_OP_ASSERT_LINE_START: + { + JERRY_DEBUG_MSG ("ASSERT_LINE_START\n"); + break; + } + case RE_OP_ASSERT_LINE_END: + { + JERRY_DEBUG_MSG ("ASSERT_LINE_END\n"); + break; + } + case RE_OP_ASSERT_LOOKAHEAD_POS: + { + JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_POS "); + JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++); + JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ASSERT_LOOKAHEAD_NEG: + { + JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_NEG "); + JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++); + JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p)); + JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p)); + const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p); + JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset); + break; + } + case RE_OP_ASSERT_END: + { + JERRY_DEBUG_MSG ("ASSERT_END\n"); + break; + } + case RE_OP_ASSERT_WORD_BOUNDARY: + { + JERRY_DEBUG_MSG ("ASSERT_WORD_BOUNDARY\n"); + break; + } + case RE_OP_ASSERT_NOT_WORD_BOUNDARY: + { + JERRY_DEBUG_MSG ("ASSERT_NOT_WORD_BOUNDARY\n"); + break; + } + case RE_OP_CLASS_ESCAPE: + { + ecma_class_escape_t escape = (ecma_class_escape_t) *bytecode_p++; + JERRY_DEBUG_MSG ("CLASS_ESCAPE \\%c\n", escape_chars[escape]); + break; + } + case RE_OP_CHAR_CLASS: + { + JERRY_DEBUG_MSG ("CHAR_CLASS "); + uint8_t flags = *bytecode_p++; + uint32_t char_count = (flags & RE_CLASS_HAS_CHARS) ? re_get_value (&bytecode_p) : 0; + uint32_t range_count = (flags & RE_CLASS_HAS_RANGES) ? re_get_value (&bytecode_p) : 0; + + if (flags & RE_CLASS_INVERT) + { + JERRY_DEBUG_MSG ("inverted "); + } + + JERRY_DEBUG_MSG ("escapes: "); + uint8_t escape_count = flags & RE_CLASS_ESCAPE_COUNT_MASK; + while (escape_count--) + { + JERRY_DEBUG_MSG ("\\%c, ", escape_chars[*bytecode_p++]); + } + + JERRY_DEBUG_MSG ("chars: "); + while (char_count--) + { + JERRY_DEBUG_MSG ("\\u%04x, ", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE)); + } + + JERRY_DEBUG_MSG ("ranges: "); + while (range_count--) + { + const lit_code_point_t begin = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE); + const lit_code_point_t end = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE); + JERRY_DEBUG_MSG ("\\u%04x-\\u%04x, ", begin, end); + } + + JERRY_DEBUG_MSG ("\n"); + break; + } + case RE_OP_UNICODE_PERIOD: + { + JERRY_DEBUG_MSG ("UNICODE_PERIOD\n"); + break; + } + case RE_OP_PERIOD: + { + JERRY_DEBUG_MSG ("PERIOD\n"); + break; + } + case RE_OP_CHAR: + { + JERRY_DEBUG_MSG ("CHAR \\u%04x\n", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE)); + break; + } + case RE_OP_BYTE: + { + const uint8_t ch = *bytecode_p++; + JERRY_DEBUG_MSG ("BYTE \\u%04x '%c'\n", ch, (char) ch); + break; + } + case RE_OP_EOF: + { + JERRY_DEBUG_MSG ("EOF\n"); + return; + } + default: + { + JERRY_DEBUG_MSG ("UNKNOWN(%d)\n", (uint32_t) op); + break; + } + } + } +} /* re_dump_bytecode */ +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.h new file mode 100644 index 00000000..9fd8456d --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-bytecode.h @@ -0,0 +1,131 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_BYTECODE_H +#define RE_BYTECODE_H + +#include "ecma-globals.h" + +#include "re-compiler-context.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_bytecode Bytecode + * @{ + */ + +/** + * Size of the RegExp bytecode cache + */ +#define RE_CACHE_SIZE 8u + +/** + * Maximum value that can be encoded in the RegExp bytecode as a single byte. + */ +#define RE_VALUE_1BYTE_MAX 0xFE + +/** + * Marker that signals that the actual value is enocded in the following 4 bytes in the bytecode. + */ +#define RE_VALUE_4BYTE_MARKER 0xFF + +/** + * RegExp opcodes + */ +typedef enum +{ + RE_OP_EOF, /**< end of pattern */ + + RE_OP_ALTERNATIVE_START, /**< start of alternatives */ + RE_OP_ALTERNATIVE_NEXT, /**< next alternative */ + RE_OP_NO_ALTERNATIVE, /**< no alternative */ + + RE_OP_CAPTURING_GROUP_START, /**< start of a capturing group */ + RE_OP_NON_CAPTURING_GROUP_START, /**< start of a non-capturing group */ + + RE_OP_GREEDY_CAPTURING_GROUP_END, /**< end of a greedy capturing group */ + RE_OP_GREEDY_NON_CAPTURING_GROUP_END, /**< end of a greedy non-capturing group */ + RE_OP_LAZY_CAPTURING_GROUP_END, /**< end of a lazy capturing group */ + RE_OP_LAZY_NON_CAPTURING_GROUP_END, /**< end of a lazy non-capturing group */ + + RE_OP_GREEDY_ITERATOR, /**< greedy iterator */ + RE_OP_LAZY_ITERATOR, /**< lazy iterator */ + RE_OP_ITERATOR_END, /*** end of an iterator */ + + RE_OP_BACKREFERENCE, /**< backreference */ + + RE_OP_ASSERT_LINE_START, /**< line start assertion */ + RE_OP_ASSERT_LINE_END, /**< line end assertion */ + RE_OP_ASSERT_WORD_BOUNDARY, /**< word boundary assertion */ + RE_OP_ASSERT_NOT_WORD_BOUNDARY, /**< not word boundary assertion */ + RE_OP_ASSERT_LOOKAHEAD_POS, /**< positive lookahead assertion */ + RE_OP_ASSERT_LOOKAHEAD_NEG, /**< negative lookahead assertion */ + RE_OP_ASSERT_END, /**< end of an assertion */ + + RE_OP_CLASS_ESCAPE, /**< class escape */ + RE_OP_CHAR_CLASS, /**< character class */ + RE_OP_UNICODE_PERIOD, /**< period in full unicode mode */ + RE_OP_PERIOD, /**< period in non-unicode mode */ + RE_OP_CHAR, /**< any code point */ + RE_OP_BYTE, /**< 1-byte utf8 character */ +} re_opcode_t; + +/** + * Compiled byte code data. + */ +typedef struct +{ + ecma_compiled_code_t header; /**< compiled code header */ + uint32_t captures_count; /**< number of capturing groups */ + uint32_t non_captures_count; /**< number of non-capturing groups */ + ecma_value_t source; /**< original RegExp pattern */ +} re_compiled_code_t; + +void re_initialize_regexp_bytecode (re_compiler_ctx_t *re_ctx_p); +uint32_t re_bytecode_size (re_compiler_ctx_t *re_ctx_p); + +void re_append_opcode (re_compiler_ctx_t *re_ctx_p, const re_opcode_t opcode); +void re_append_byte (re_compiler_ctx_t *re_ctx_p, const uint8_t byte); +void re_append_char (re_compiler_ctx_t *re_ctx_p, const lit_code_point_t cp); +void re_append_value (re_compiler_ctx_t *re_ctx_p, const uint32_t value); + +void re_insert_opcode (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const re_opcode_t opcode); +void re_insert_byte (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const uint8_t byte); +void re_insert_char (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const lit_code_point_t cp); +void re_insert_value (re_compiler_ctx_t *re_ctx_p, const uint32_t offset, const uint32_t value); + +re_opcode_t re_get_opcode (const uint8_t **bc_p); +uint8_t re_get_byte (const uint8_t **bc_p); +lit_code_point_t re_get_char (const uint8_t **bc_p, bool unicode); +uint32_t re_get_value (const uint8_t **bc_p); + +#if JERRY_REGEXP_DUMP_BYTE_CODE +void re_dump_bytecode (re_compiler_ctx_t *bc_ctx); +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_BYTECODE_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler-context.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler-context.h new file mode 100644 index 00000000..b7dbb029 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler-context.h @@ -0,0 +1,60 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_COMPILER_CONTEXT_H +#define RE_COMPILER_CONTEXT_H + +#include "re-token.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_compiler Compiler + * @{ + */ + +/** + * RegExp compiler context + */ +typedef struct +{ + const lit_utf8_byte_t *input_start_p; /**< start of input pattern */ + const lit_utf8_byte_t *input_curr_p; /**< current position in input pattern */ + const lit_utf8_byte_t *input_end_p; /**< end of input pattern */ + + uint8_t *bytecode_start_p; /**< start of bytecode block */ + size_t bytecode_size; /**< size of bytecode */ + + uint32_t captures_count; /**< number of capture groups */ + uint32_t non_captures_count; /**< number of non-capture groups */ + + int groups_count; /**< number of groups */ + uint16_t flags; /**< RegExp flags */ + re_token_t token; /**< current token */ +} re_compiler_ctx_t; + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_COMPILER_CONTEXT_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.cpp new file mode 100644 index 00000000..a495616b --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.cpp @@ -0,0 +1,184 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "re-compiler.h" + +#include "ecma-exceptions.h" +#include "ecma-helpers.h" +#include "ecma-regexp-object.h" + +#include "jcontext.h" +#include "jmem.h" +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "re-bytecode.h" +#include "re-compiler-context.h" +#include "re-parser.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_compiler Compiler + * @{ + */ + +/** + * Search for the given pattern in the RegExp cache. + * + * @return pointer to bytecode if found + * NULL - otherwise + */ +static re_compiled_code_t * +re_cache_lookup (ecma_string_t *pattern_str_p, /**< pattern string */ + uint16_t flags) /**< flags */ +{ + re_compiled_code_t **cache_p = JERRY_CONTEXT (re_cache); + + for (uint8_t idx = 0u; idx < RE_CACHE_SIZE; idx++) + { + re_compiled_code_t *cached_bytecode_p = cache_p[idx]; + + if (cached_bytecode_p == NULL) + { + break; + } + + ecma_string_t *cached_pattern_str_p = ecma_get_string_from_value (cached_bytecode_p->source); + + if (cached_bytecode_p->header.status_flags == flags + && ecma_compare_ecma_strings (cached_pattern_str_p, pattern_str_p)) + { + return cached_bytecode_p; + } + } + + return NULL; +} /* re_cache_lookup */ + +/** + * Run garbage collection in RegExp cache. + */ +void +re_cache_gc (void) +{ + re_compiled_code_t **cache_p = JERRY_CONTEXT (re_cache); + + for (uint32_t i = 0u; i < RE_CACHE_SIZE; i++) + { + const re_compiled_code_t *cached_bytecode_p = cache_p[i]; + + if (cached_bytecode_p == NULL) + { + break; + } + + ecma_bytecode_deref ((ecma_compiled_code_t *) cached_bytecode_p); + cache_p[i] = NULL; + } + + JERRY_CONTEXT (re_cache_idx) = 0; +} /* re_cache_gc */ + +/** + * Compilation of RegExp bytecode + * + * @return pointer to bytecode if compilation was successful + * NULL - otherwise + */ +re_compiled_code_t * +re_compile_bytecode (ecma_string_t *pattern_str_p, /**< pattern */ + uint16_t flags) /**< flags */ +{ + re_compiled_code_t *cached_bytecode_p = re_cache_lookup (pattern_str_p, flags); + + if (cached_bytecode_p != NULL) + { + ecma_bytecode_ref ((ecma_compiled_code_t *) cached_bytecode_p); + return cached_bytecode_p; + } + + re_compiler_ctx_t re_ctx; + re_ctx.flags = flags; + re_ctx.captures_count = 1; + re_ctx.non_captures_count = 0; + + re_initialize_regexp_bytecode (&re_ctx); + + ECMA_STRING_TO_UTF8_STRING (pattern_str_p, pattern_start_p, pattern_start_size); + + re_ctx.input_start_p = pattern_start_p; + re_ctx.input_curr_p = (lit_utf8_byte_t *) pattern_start_p; + re_ctx.input_end_p = pattern_start_p + pattern_start_size; + re_ctx.groups_count = -1; + + /* Parse RegExp pattern */ + ecma_value_t result = re_parse_alternative (&re_ctx, true); + + ECMA_FINALIZE_UTF8_STRING (pattern_start_p, pattern_start_size); + + if (ECMA_IS_VALUE_ERROR (result)) + { + /* Compilation failed, free bytecode. */ + jmem_heap_free_block (re_ctx.bytecode_start_p, re_ctx.bytecode_size); + return NULL; + } + + /* Align bytecode size to JMEM_ALIGNMENT so that it can be stored in the bytecode header. */ + const uint32_t final_size = JERRY_ALIGNUP (re_ctx.bytecode_size, JMEM_ALIGNMENT); + re_compiled_code_t *re_compiled_code_p = + (re_compiled_code_t *) jmem_heap_realloc_block (re_ctx.bytecode_start_p, re_ctx.bytecode_size, final_size); + + /* Bytecoded will be inserted into the cache and returned to the caller, so refcount is implicitly set to 2. */ + re_compiled_code_p->header.refs = 2; + re_compiled_code_p->header.size = (uint16_t) (final_size >> JMEM_ALIGNMENT_LOG); + re_compiled_code_p->header.status_flags = re_ctx.flags; + + ecma_ref_ecma_string (pattern_str_p); + re_compiled_code_p->source = ecma_make_string_value (pattern_str_p); + re_compiled_code_p->captures_count = re_ctx.captures_count; + re_compiled_code_p->non_captures_count = re_ctx.non_captures_count; + +#if JERRY_REGEXP_DUMP_BYTE_CODE + if (JERRY_CONTEXT (jerry_init_flags) & JERRY_INIT_SHOW_REGEXP_OPCODES) + { + re_dump_bytecode (&re_ctx); + } +#endif /* JERRY_REGEXP_DUMP_BYTE_CODE */ + + uint8_t cache_idx = JERRY_CONTEXT (re_cache_idx); + + if (JERRY_CONTEXT (re_cache)[cache_idx] != NULL) + { + ecma_bytecode_deref ((ecma_compiled_code_t *) JERRY_CONTEXT (re_cache)[cache_idx]); + } + + JERRY_CONTEXT (re_cache)[cache_idx] = re_compiled_code_p; + JERRY_CONTEXT (re_cache_idx) = (uint8_t) (cache_idx + 1) % RE_CACHE_SIZE; + + return re_compiled_code_p; +} /* re_compile_bytecode */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.h new file mode 100644 index 00000000..ace781ef --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-compiler.h @@ -0,0 +1,46 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_COMPILER_H +#define RE_COMPILER_H + +#include "ecma-globals.h" + +#include "re-bytecode.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_compiler Compiler + * @{ + */ + +re_compiled_code_t *re_compile_bytecode (ecma_string_t *pattern_str_p, uint16_t flags); + +void re_cache_gc (void); + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_COMPILER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.cpp b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.cpp new file mode 100644 index 00000000..93114df4 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.cpp @@ -0,0 +1,1327 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "re-parser.h" + +#include "ecma-exceptions.h" +#include "ecma-globals.h" + +#include "jcontext.h" +#include "jrt-libc-includes.h" +#include "lit-char-helpers.h" +#include "re-compiler.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * Get the start opcode for the current group. + * + * @return RegExp opcode + */ +static re_opcode_t +re_get_group_start_opcode (bool is_capturing) /**< is capturing group */ +{ + return (is_capturing) ? RE_OP_CAPTURING_GROUP_START : RE_OP_NON_CAPTURING_GROUP_START; +} /* re_get_group_start_opcode */ + +/** + * Get the end opcode for the current group. + * + * @return RegExp opcode + */ +static re_opcode_t +re_get_group_end_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + bool is_capturing) /**< is capturing group */ +{ + if (is_capturing) + { + if (re_ctx_p->token.greedy) + { + return RE_OP_GREEDY_CAPTURING_GROUP_END; + } + + return RE_OP_LAZY_CAPTURING_GROUP_END; + } + + if (re_ctx_p->token.greedy) + { + return RE_OP_GREEDY_NON_CAPTURING_GROUP_END; + } + + return RE_OP_LAZY_NON_CAPTURING_GROUP_END; +} /* re_get_group_end_opcode */ + +/** + * Enclose the given bytecode to a group. + */ +static void +re_insert_into_group (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t group_start_offset, /**< offset of group start */ + uint32_t idx, /**< index of group */ + uint32_t capture_start, /**< index of first nested capture */ + bool is_capturing) /**< is capturing group */ +{ + uint32_t qmin = re_ctx_p->token.qmin; + uint32_t qmax = re_ctx_p->token.qmax; + + if (JERRY_UNLIKELY (!is_capturing && re_bytecode_size (re_ctx_p) == group_start_offset)) + { + return; + } + + if (qmin == 0) + { + re_insert_value (re_ctx_p, group_start_offset, re_bytecode_size (re_ctx_p) - group_start_offset); + } + + re_insert_value (re_ctx_p, group_start_offset, qmin); + re_insert_value (re_ctx_p, group_start_offset, re_ctx_p->captures_count - capture_start); + + if (!is_capturing) + { + re_insert_value (re_ctx_p, group_start_offset, capture_start); + } + else + { + JERRY_ASSERT (idx == capture_start); + } + + re_insert_value (re_ctx_p, group_start_offset, idx); + re_insert_opcode (re_ctx_p, group_start_offset, re_get_group_start_opcode (is_capturing)); + + re_append_opcode (re_ctx_p, re_get_group_end_opcode (re_ctx_p, is_capturing)); + re_append_value (re_ctx_p, idx); + re_append_value (re_ctx_p, qmin); + re_append_value (re_ctx_p, qmax + RE_QMAX_OFFSET); +} /* re_insert_into_group */ + +/** + * Insert simple atom iterator. + */ +static void +re_insert_atom_iterator (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t start_offset) /**< atom start offset */ +{ + const uint32_t qmin = re_ctx_p->token.qmin; + const uint32_t qmax = re_ctx_p->token.qmax; + + if (qmin == 1 && qmax == 1) + { + return; + } + + re_append_opcode (re_ctx_p, RE_OP_ITERATOR_END); + re_insert_value (re_ctx_p, start_offset, re_bytecode_size (re_ctx_p) - start_offset); + re_insert_value (re_ctx_p, start_offset, qmax + RE_QMAX_OFFSET); + re_insert_value (re_ctx_p, start_offset, qmin); + re_insert_opcode (re_ctx_p, start_offset, re_ctx_p->token.greedy ? RE_OP_GREEDY_ITERATOR : RE_OP_LAZY_ITERATOR); +} /* re_insert_atom_iterator */ + +/** + * Insert a lookahead assertion. + */ +static void +re_insert_assertion_lookahead (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t start_offset, /**< atom start offset */ + uint32_t capture_start, /**< index of first nested capture */ + bool negative) /** lookahead type */ +{ + const uint32_t qmin = re_ctx_p->token.qmin; + + re_append_opcode (re_ctx_p, RE_OP_ASSERT_END); + re_insert_value (re_ctx_p, start_offset, re_bytecode_size (re_ctx_p) - start_offset); + + /* We need to clear nested capturing group results when a negative assertion or the tail after a positive assertion + * does not match, so we store the begin and end index of nested capturing groups. */ + re_insert_value (re_ctx_p, start_offset, re_ctx_p->captures_count - capture_start); + re_insert_value (re_ctx_p, start_offset, capture_start); + + /* Lookaheads always result in zero length matches, which means iterations will always stop on the first match. + * This allows us to not have to deal with iterations beyond one. Either qmin == 0 which will implicitly match, + * or qmin > 0, in which case the first iteration will decide whether the assertion matches depending on whether + * the iteration matched or not. This also allows us to ignore qmax entirely. */ + re_insert_byte (re_ctx_p, start_offset, (uint8_t) JERRY_MIN (qmin, 1)); + + const re_opcode_t opcode = (negative) ? RE_OP_ASSERT_LOOKAHEAD_NEG : RE_OP_ASSERT_LOOKAHEAD_POS; + re_insert_opcode (re_ctx_p, start_offset, opcode); +} /* re_insert_assertion_lookahead */ + +/** + * Consume non greedy (question mark) character if present. + */ +static void +re_parse_lazy_char (re_compiler_ctx_t *re_ctx_p) /**< RegExp parser context */ +{ + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && *re_ctx_p->input_curr_p == LIT_CHAR_QUESTION) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.greedy = false; + return; + } + + re_ctx_p->token.greedy = true; +} /* re_parse_lazy_char */ + +/** + * Parse a max 3 digit long octal number from the input string, with a decimal value less than 256. + * + * @return value of the octal number + */ +static uint32_t +re_parse_octal (re_compiler_ctx_t *re_ctx_p) /**< RegExp parser context */ +{ + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + JERRY_ASSERT (lit_char_is_octal_digit (*re_ctx_p->input_curr_p)); + + uint32_t value = (uint32_t) (*re_ctx_p->input_curr_p++) - LIT_CHAR_0; + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && lit_char_is_octal_digit (*re_ctx_p->input_curr_p)) + { + value = value * 8 + (*re_ctx_p->input_curr_p++) - LIT_CHAR_0; + } + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && lit_char_is_octal_digit (*re_ctx_p->input_curr_p)) + { + const uint32_t new_value = value * 8 + (*re_ctx_p->input_curr_p) - LIT_CHAR_0; + + if (new_value <= RE_MAX_OCTAL_VALUE) + { + value = new_value; + re_ctx_p->input_curr_p++; + } + } + + return value; +} /* re_parse_octal */ + +/** + * Check that the currently parsed quantifier is valid. + * + * @return ECMA_VALUE_ERROR, if quantifier is invalid + * ECMA_VALUE_EMPTY, otherwise + */ +static ecma_value_t +re_check_quantifier (re_compiler_ctx_t *re_ctx_p) +{ + if (re_ctx_p->token.qmin > re_ctx_p->token.qmax) + { + /* ECMA-262 v5.1 15.10.2.5 */ + return ecma_raise_syntax_error (ECMA_ERR_MIN_GREATER_THAN_MAX); + } + + return ECMA_VALUE_EMPTY; +} /* re_check_quantifier */ + +/** + * Parse RegExp quantifier. + * + * @return ECMA_VALUE_TRUE - if parsed successfully + * ECMA_VALUE_FALSE - otherwise + */ +static ecma_value_t +re_parse_quantifier (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p) + { + switch (*re_ctx_p->input_curr_p) + { + case LIT_CHAR_QUESTION: + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.qmin = 0; + re_ctx_p->token.qmax = 1; + + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + case LIT_CHAR_ASTERISK: + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.qmin = 0; + re_ctx_p->token.qmax = RE_INFINITY; + + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + case LIT_CHAR_PLUS: + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.qmin = 1; + re_ctx_p->token.qmax = RE_INFINITY; + + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + case LIT_CHAR_LEFT_BRACE: + { + const lit_utf8_byte_t *current_p = re_ctx_p->input_curr_p + 1; + uint32_t qmin = 0; + uint32_t qmax = RE_INFINITY; + + if (current_p >= re_ctx_p->input_end_p) + { + break; + } + + if (!lit_char_is_decimal_digit (*current_p)) + { + break; + } + + qmin = lit_parse_decimal (¤t_p, re_ctx_p->input_end_p); + + if (current_p >= re_ctx_p->input_end_p) + { + break; + } + + lit_utf8_byte_t ch = *current_p++; + if (ch == LIT_CHAR_RIGHT_BRACE) + { + qmax = qmin; + } + else if (ch == LIT_CHAR_COMMA) + { + if (current_p >= re_ctx_p->input_end_p) + { + break; + } + + if (lit_char_is_decimal_digit (*current_p)) + { + qmax = lit_parse_decimal (¤t_p, re_ctx_p->input_end_p); + } + + if (current_p >= re_ctx_p->input_end_p || *current_p++ != LIT_CHAR_RIGHT_BRACE) + { + break; + } + } + else + { + break; + } + + re_ctx_p->token.qmin = qmin; + re_ctx_p->token.qmax = qmax; + re_ctx_p->input_curr_p = current_p; + re_parse_lazy_char (re_ctx_p); + return ECMA_VALUE_TRUE; + } + default: + { + break; + } + } + } + + re_ctx_p->token.qmin = 1; + re_ctx_p->token.qmax = 1; + re_ctx_p->token.greedy = true; + + return ECMA_VALUE_FALSE; +} /* re_parse_quantifier */ + +/** + * Count the number of groups in the current pattern. + */ +static void +re_count_groups (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + bool is_char_class = 0; + re_ctx_p->groups_count = 0; + const lit_utf8_byte_t *curr_p = re_ctx_p->input_start_p; + + while (curr_p < re_ctx_p->input_end_p) + { + switch (*curr_p++) + { + case LIT_CHAR_BACKSLASH: + { + if (curr_p < re_ctx_p->input_end_p) + { + lit_utf8_incr (&curr_p); + } + break; + } + case LIT_CHAR_LEFT_SQUARE: + { + is_char_class = true; + break; + } + case LIT_CHAR_RIGHT_SQUARE: + { + is_char_class = false; + break; + } + case LIT_CHAR_LEFT_PAREN: + { + if (curr_p < re_ctx_p->input_end_p && *curr_p != LIT_CHAR_QUESTION && !is_char_class) + { + re_ctx_p->groups_count++; + } + break; + } + } + } +} /* re_count_groups */ + +/** + * Check if a code point is a Syntax character + * + * @return true, if syntax character + * false, otherwise + */ +static bool +re_is_syntax_char (lit_code_point_t cp) /**< code point */ +{ + return (cp == LIT_CHAR_CIRCUMFLEX || cp == LIT_CHAR_DOLLAR_SIGN || cp == LIT_CHAR_BACKSLASH || cp == LIT_CHAR_DOT + || cp == LIT_CHAR_ASTERISK || cp == LIT_CHAR_PLUS || cp == LIT_CHAR_QUESTION || cp == LIT_CHAR_LEFT_PAREN + || cp == LIT_CHAR_RIGHT_PAREN || cp == LIT_CHAR_LEFT_SQUARE || cp == LIT_CHAR_RIGHT_SQUARE + || cp == LIT_CHAR_LEFT_BRACE || cp == LIT_CHAR_RIGHT_BRACE || cp == LIT_CHAR_VLINE); +} /* re_is_syntax_char */ + +/** + * Parse a Character Escape or a Character Class Escape. + * + * @return ECMA_VALUE_EMPTY, if parsed successfully + * ECMA_VALUE_ERROR, otherwise + */ +static ecma_value_t +re_parse_char_escape (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + re_ctx_p->token.type = RE_TOK_CHAR; + + if (lit_char_is_decimal_digit (*re_ctx_p->input_curr_p)) + { + /* NULL code point escape, only valid if there are no following digits. */ + if (*re_ctx_p->input_curr_p == LIT_CHAR_0 + && (re_ctx_p->input_curr_p + 1 >= re_ctx_p->input_end_p + || !lit_char_is_decimal_digit (re_ctx_p->input_curr_p[1]))) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.value = LIT_UNICODE_CODE_POINT_NULL; + return ECMA_VALUE_EMPTY; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE_SEQUENCE); + } + + /* Legacy octal escape sequence */ + if (lit_char_is_octal_digit (*re_ctx_p->input_curr_p)) + { + re_ctx_p->token.value = re_parse_octal (re_ctx_p); + return ECMA_VALUE_EMPTY; + } + + /* Identity escape */ + re_ctx_p->token.value = *re_ctx_p->input_curr_p++; + return ECMA_VALUE_EMPTY; + } + + lit_code_point_t ch = lit_cesu8_read_next (&re_ctx_p->input_curr_p); + switch (ch) + { + /* Character Class escapes */ + case LIT_CHAR_LOWERCASE_D: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_DIGIT; + break; + } + case LIT_CHAR_UPPERCASE_D: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_NOT_DIGIT; + break; + } + case LIT_CHAR_LOWERCASE_S: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_WHITESPACE; + break; + } + case LIT_CHAR_UPPERCASE_S: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_NOT_WHITESPACE; + break; + } + case LIT_CHAR_LOWERCASE_W: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_WORD_CHAR; + break; + } + case LIT_CHAR_UPPERCASE_W: + { + re_ctx_p->token.type = RE_TOK_CLASS_ESCAPE; + re_ctx_p->token.value = RE_ESCAPE_NOT_WORD_CHAR; + break; + } + /* Control escapes */ + case LIT_CHAR_LOWERCASE_F: + { + re_ctx_p->token.value = LIT_CHAR_FF; + break; + } + case LIT_CHAR_LOWERCASE_N: + { + re_ctx_p->token.value = LIT_CHAR_LF; + break; + } + case LIT_CHAR_LOWERCASE_R: + { + re_ctx_p->token.value = LIT_CHAR_CR; + break; + } + case LIT_CHAR_LOWERCASE_T: + { + re_ctx_p->token.value = LIT_CHAR_TAB; + break; + } + case LIT_CHAR_LOWERCASE_V: + { + re_ctx_p->token.value = LIT_CHAR_VTAB; + break; + } + /* Control letter */ + case LIT_CHAR_LOWERCASE_C: + { + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p) + { + ch = *re_ctx_p->input_curr_p; + + if ((ch >= LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_UPPERCASE_LETTERS_END) + || (ch >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_END)) + { + re_ctx_p->token.value = (ch % 32); + re_ctx_p->input_curr_p++; + + break; + } + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_CONTROL_ESCAPE_SEQUENCE); + } + + re_ctx_p->token.value = LIT_CHAR_BACKSLASH; + re_ctx_p->input_curr_p--; + + break; + } + /* Hex escape */ + case LIT_CHAR_LOWERCASE_X: + { + uint32_t hex_value = lit_char_hex_lookup (re_ctx_p->input_curr_p, re_ctx_p->input_end_p, 2); + if (hex_value != UINT32_MAX) + { + re_ctx_p->token.value = hex_value; + re_ctx_p->input_curr_p += 2; + break; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_HEX_ESCAPE_SEQUENCE); + } + + re_ctx_p->token.value = LIT_CHAR_LOWERCASE_X; + break; + } + /* Unicode escape */ + case LIT_CHAR_LOWERCASE_U: + { + uint32_t hex_value = lit_char_hex_lookup (re_ctx_p->input_curr_p, re_ctx_p->input_end_p, 4); + if (hex_value != UINT32_MAX) + { + re_ctx_p->token.value = hex_value; + re_ctx_p->input_curr_p += 4; + + if (re_ctx_p->flags & RE_FLAG_UNICODE && lit_is_code_point_utf16_high_surrogate (re_ctx_p->token.value) + && re_ctx_p->input_curr_p + 6 <= re_ctx_p->input_end_p && re_ctx_p->input_curr_p[0] == '\\' + && re_ctx_p->input_curr_p[1] == 'u') + { + hex_value = lit_char_hex_lookup (re_ctx_p->input_curr_p + 2, re_ctx_p->input_end_p, 4); + if (lit_is_code_point_utf16_low_surrogate (hex_value)) + { + re_ctx_p->token.value = + lit_convert_surrogate_pair_to_code_point ((ecma_char_t) re_ctx_p->token.value, (ecma_char_t) hex_value); + re_ctx_p->input_curr_p += 6; + } + } + + break; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + if (re_ctx_p->input_curr_p + 1 < re_ctx_p->input_end_p && re_ctx_p->input_curr_p[0] == LIT_CHAR_LEFT_BRACE + && lit_char_is_hex_digit (re_ctx_p->input_curr_p[1])) + { + lit_code_point_t cp = lit_char_hex_to_int (re_ctx_p->input_curr_p[1]); + re_ctx_p->input_curr_p += 2; + + while (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && lit_char_is_hex_digit (*re_ctx_p->input_curr_p)) + { + cp = cp * 16 + lit_char_hex_to_int (*re_ctx_p->input_curr_p++); + + if (JERRY_UNLIKELY (cp > LIT_UNICODE_CODE_POINT_MAX)) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + } + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && *re_ctx_p->input_curr_p == LIT_CHAR_RIGHT_BRACE) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.value = cp; + break; + } + } + + return ecma_raise_syntax_error (ECMA_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE); + } + + re_ctx_p->token.value = LIT_CHAR_LOWERCASE_U; + break; + } + /* Identity escape */ + default: + { + /* Must be '/', or one of SyntaxCharacter */ + if (re_ctx_p->flags & RE_FLAG_UNICODE && ch != LIT_CHAR_SLASH && !re_is_syntax_char (ch)) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE); + } + re_ctx_p->token.value = ch; + } + } + + return ECMA_VALUE_EMPTY; +} /* re_parse_char_escape */ + +/** + * Read the input pattern and parse the next token for the RegExp compiler + * + * @return empty ecma value - if parsed successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +re_parse_next_token (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + re_ctx_p->token.type = RE_TOK_EOF; + return ECMA_VALUE_EMPTY; + } + + ecma_char_t ch = lit_cesu8_read_next (&re_ctx_p->input_curr_p); + + switch (ch) + { + case LIT_CHAR_CIRCUMFLEX: + { + re_ctx_p->token.type = RE_TOK_ASSERT_START; + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_DOLLAR_SIGN: + { + re_ctx_p->token.type = RE_TOK_ASSERT_END; + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_VLINE: + { + re_ctx_p->token.type = RE_TOK_ALTERNATIVE; + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_DOT: + { + re_ctx_p->token.type = RE_TOK_PERIOD; + /* Check quantifier */ + break; + } + case LIT_CHAR_BACKSLASH: + { + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE); + } + + /* DecimalEscape, Backreferences cannot start with a zero digit. */ + if (*re_ctx_p->input_curr_p > LIT_CHAR_0 && *re_ctx_p->input_curr_p <= LIT_CHAR_9) + { + const lit_utf8_byte_t *digits_p = re_ctx_p->input_curr_p; + const uint32_t value = lit_parse_decimal (&digits_p, re_ctx_p->input_end_p); + + if (re_ctx_p->groups_count < 0) + { + re_count_groups (re_ctx_p); + } + + if (value <= (uint32_t) re_ctx_p->groups_count) + { + /* Valid backreference */ + re_ctx_p->input_curr_p = digits_p; + re_ctx_p->token.type = RE_TOK_BACKREFERENCE; + re_ctx_p->token.value = value; + + /* Check quantifier */ + break; + } + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_LOWERCASE_B) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.type = RE_TOK_ASSERT_WORD_BOUNDARY; + return ECMA_VALUE_EMPTY; + } + else if (*re_ctx_p->input_curr_p == LIT_CHAR_UPPERCASE_B) + { + re_ctx_p->input_curr_p++; + re_ctx_p->token.type = RE_TOK_ASSERT_NOT_WORD_BOUNDARY; + return ECMA_VALUE_EMPTY; + } + + const ecma_value_t parse_result = re_parse_char_escape (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (parse_result)) + { + return parse_result; + } + + /* Check quantifier */ + break; + } + case LIT_CHAR_LEFT_PAREN: + { + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_UNTERMINATED_GROUP); + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_QUESTION) + { + re_ctx_p->input_curr_p++; + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_GROUP); + } + + ch = *re_ctx_p->input_curr_p++; + + if (ch == LIT_CHAR_EQUALS) + { + re_ctx_p->token.type = RE_TOK_ASSERT_LOOKAHEAD; + re_ctx_p->token.value = false; + } + else if (ch == LIT_CHAR_EXCLAMATION) + { + re_ctx_p->token.type = RE_TOK_ASSERT_LOOKAHEAD; + re_ctx_p->token.value = true; + } + else if (ch == LIT_CHAR_COLON) + { + re_ctx_p->token.type = RE_TOK_START_NON_CAPTURE_GROUP; + } + else + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_GROUP); + } + } + else + { + re_ctx_p->token.type = RE_TOK_START_CAPTURE_GROUP; + } + + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_RIGHT_PAREN: + { + re_ctx_p->token.type = RE_TOK_END_GROUP; + + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_LEFT_SQUARE: + { + re_ctx_p->token.type = RE_TOK_CHAR_CLASS; + + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_UNTERMINATED_CHARACTER_CLASS); + } + + return ECMA_VALUE_EMPTY; + } + case LIT_CHAR_QUESTION: + case LIT_CHAR_ASTERISK: + case LIT_CHAR_PLUS: + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_QUANTIFIER); + } + case LIT_CHAR_LEFT_BRACE: + { + re_ctx_p->input_curr_p--; + if (ecma_is_value_true (re_parse_quantifier (re_ctx_p))) + { + return ecma_raise_syntax_error (ECMA_ERR_NOTHING_TO_REPEAT); + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_LONE_QUANTIFIER_BRACKET); + } + + re_ctx_p->input_curr_p++; + re_ctx_p->token.type = RE_TOK_CHAR; + re_ctx_p->token.value = ch; + + /* Check quantifier */ + break; + } + case LIT_CHAR_RIGHT_SQUARE: + case LIT_CHAR_RIGHT_BRACE: + { + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_LONE_QUANTIFIER_BRACKET); + } + + /* FALLTHRU */ + } + default: + { + re_ctx_p->token.type = RE_TOK_CHAR; + re_ctx_p->token.value = ch; + + if (re_ctx_p->flags & RE_FLAG_UNICODE && lit_is_code_point_utf16_high_surrogate (ch) + && re_ctx_p->input_curr_p < re_ctx_p->input_end_p) + { + const ecma_char_t next = lit_cesu8_peek_next (re_ctx_p->input_curr_p); + if (lit_is_code_point_utf16_low_surrogate (next)) + { + re_ctx_p->token.value = lit_convert_surrogate_pair_to_code_point (ch, next); + re_ctx_p->input_curr_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT; + } + } + + /* Check quantifier */ + break; + } + } + + re_parse_quantifier (re_ctx_p); + return re_check_quantifier (re_ctx_p); +} /* re_parse_next_token */ + +/** + * Append a character class range to the bytecode. + */ +static void +re_class_add_range (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + lit_code_point_t start, /**< range begin */ + lit_code_point_t end) /**< range end */ +{ + if (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) + { + start = ecma_regexp_canonicalize_char (start, re_ctx_p->flags & RE_FLAG_UNICODE); + end = ecma_regexp_canonicalize_char (end, re_ctx_p->flags & RE_FLAG_UNICODE); + } + + re_append_char (re_ctx_p, start); + re_append_char (re_ctx_p, end); +} /* re_class_add_range */ + +/** + * Add a single character to the character class + */ +static void +re_class_add_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + uint32_t class_offset, /**< character class bytecode offset*/ + lit_code_point_t cp) /**< code point */ +{ + if (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) + { + cp = ecma_regexp_canonicalize_char (cp, re_ctx_p->flags & RE_FLAG_UNICODE); + } + + re_insert_char (re_ctx_p, class_offset, cp); +} /* re_class_add_char */ + +/** + * Invalid character code point + */ +#define RE_INVALID_CP 0xFFFFFFFF + +/** + * Read the input pattern and parse the range of character class + * + * @return empty ecma value - if parsed successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +re_parse_char_class (re_compiler_ctx_t *re_ctx_p) /**< RegExp compiler context */ +{ + static const uint8_t escape_flags[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20 }; + const uint32_t class_offset = re_bytecode_size (re_ctx_p); + + uint8_t found_escape_flags = 0; + uint8_t out_class_flags = 0; + + uint32_t range_count = 0; + uint32_t char_count = 0; + bool is_range = false; + + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + if (*re_ctx_p->input_curr_p == LIT_CHAR_CIRCUMFLEX) + { + re_ctx_p->input_curr_p++; + out_class_flags |= RE_CLASS_INVERT; + } + + lit_code_point_t start = RE_INVALID_CP; + + while (true) + { + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_UNTERMINATED_CHARACTER_CLASS); + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_RIGHT_SQUARE) + { + if (is_range) + { + if (start != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, start); + char_count++; + } + + re_class_add_char (re_ctx_p, class_offset, LIT_CHAR_MINUS); + char_count++; + } + + re_ctx_p->input_curr_p++; + break; + } + + JERRY_ASSERT (re_ctx_p->input_curr_p < re_ctx_p->input_end_p); + lit_code_point_t current; + + if (*re_ctx_p->input_curr_p == LIT_CHAR_BACKSLASH) + { + re_ctx_p->input_curr_p++; + if (re_ctx_p->input_curr_p >= re_ctx_p->input_end_p) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_ESCAPE); + } + + if (*re_ctx_p->input_curr_p == LIT_CHAR_LOWERCASE_B) + { + re_ctx_p->input_curr_p++; + current = LIT_CHAR_BS; + } + else if (*re_ctx_p->input_curr_p == LIT_CHAR_MINUS) + { + re_ctx_p->input_curr_p++; + current = LIT_CHAR_MINUS; + } + else if ((re_ctx_p->flags & RE_FLAG_UNICODE) == 0 && *re_ctx_p->input_curr_p == LIT_CHAR_LOWERCASE_C + && re_ctx_p->input_curr_p + 1 < re_ctx_p->input_end_p + && (lit_char_is_decimal_digit (*(re_ctx_p->input_curr_p + 1)) + || *(re_ctx_p->input_curr_p + 1) == LIT_CHAR_UNDERSCORE)) + { + current = ((uint8_t) * (re_ctx_p->input_curr_p + 1) % 32); + re_ctx_p->input_curr_p += 2; + } + else + { + if (ECMA_IS_VALUE_ERROR (re_parse_char_escape (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + + if (re_ctx_p->token.type == RE_TOK_CLASS_ESCAPE) + { + const uint8_t escape = (uint8_t) re_ctx_p->token.value; + found_escape_flags |= escape_flags[escape]; + current = RE_INVALID_CP; + } + else + { + JERRY_ASSERT (re_ctx_p->token.type == RE_TOK_CHAR); + current = re_ctx_p->token.value; + } + } + } + else if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + current = ecma_regexp_unicode_advance (&re_ctx_p->input_curr_p, re_ctx_p->input_end_p); + } + else + { + current = lit_cesu8_read_next (&re_ctx_p->input_curr_p); + } + + if (is_range) + { + is_range = false; + + if (start != RE_INVALID_CP && current != RE_INVALID_CP) + { + if (start > current) + { + return ecma_raise_syntax_error (ECMA_ERR_RANGE_OUT_OF_ORDER_IN_CHARACTER_CLASS); + } + + re_class_add_range (re_ctx_p, start, current); + range_count++; + continue; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + return ecma_raise_syntax_error (ECMA_ERR_INVALID_CHARACTER_CLASS); + } + + if (start != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, start); + char_count++; + } + else if (current != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, current); + char_count++; + } + + re_class_add_char (re_ctx_p, class_offset, LIT_CHAR_MINUS); + char_count++; + continue; + } + + if (re_ctx_p->input_curr_p < re_ctx_p->input_end_p && *re_ctx_p->input_curr_p == LIT_CHAR_MINUS) + { + re_ctx_p->input_curr_p++; + start = current; + is_range = true; + continue; + } + + if (current != RE_INVALID_CP) + { + re_class_add_char (re_ctx_p, class_offset, current); + char_count++; + } + } + + uint8_t escape_count = 0; + for (ecma_class_escape_t escape = RE_ESCAPE__START; escape < RE_ESCAPE__COUNT; escape = (ecma_class_escape_t)((int) escape + 1)) + { + if (found_escape_flags & escape_flags[escape]) + { + re_insert_byte (re_ctx_p, class_offset, (uint8_t) escape); + escape_count++; + } + } + + if (range_count > 0) + { + re_insert_value (re_ctx_p, class_offset, range_count); + out_class_flags |= RE_CLASS_HAS_RANGES; + } + + if (char_count > 0) + { + re_insert_value (re_ctx_p, class_offset, char_count); + out_class_flags |= RE_CLASS_HAS_CHARS; + } + + JERRY_ASSERT (escape_count <= RE_CLASS_ESCAPE_COUNT_MASK); + out_class_flags |= escape_count; + + re_insert_byte (re_ctx_p, class_offset, out_class_flags); + re_insert_opcode (re_ctx_p, class_offset, RE_OP_CHAR_CLASS); + + re_parse_quantifier (re_ctx_p); + return re_check_quantifier (re_ctx_p); +} /* re_parse_char_class */ + +/** + * Parse alternatives + * + * @return empty ecma value - if alternative was successfully parsed + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +re_parse_alternative (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ + bool expect_eof) /**< expect end of file */ +{ + ECMA_CHECK_STACK_USAGE (); + uint32_t alternative_offset = re_bytecode_size (re_ctx_p); + bool first_alternative = true; + + while (true) + { + ecma_value_t next_token_result = re_parse_next_token (re_ctx_p); + if (ECMA_IS_VALUE_ERROR (next_token_result)) + { + return next_token_result; + } + + JERRY_ASSERT (ecma_is_value_empty (next_token_result)); + + uint32_t atom_offset = re_bytecode_size (re_ctx_p); + + switch (re_ctx_p->token.type) + { + case RE_TOK_START_CAPTURE_GROUP: + { + const uint32_t idx = re_ctx_p->captures_count++; + const uint32_t capture_start = idx; + + ecma_value_t result = re_parse_alternative (re_ctx_p, false); + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + re_parse_quantifier (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (re_check_quantifier (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + + re_insert_into_group (re_ctx_p, atom_offset, idx, capture_start, true); + break; + } + case RE_TOK_START_NON_CAPTURE_GROUP: + { + const uint32_t idx = re_ctx_p->non_captures_count++; + const uint32_t capture_start = re_ctx_p->captures_count; + + ecma_value_t result = re_parse_alternative (re_ctx_p, false); + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + re_parse_quantifier (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (re_check_quantifier (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + + re_insert_into_group (re_ctx_p, atom_offset, idx, capture_start, false); + break; + } + case RE_TOK_PERIOD: + { + re_append_opcode (re_ctx_p, (re_ctx_p->flags & RE_FLAG_UNICODE) ? RE_OP_UNICODE_PERIOD : RE_OP_PERIOD); + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + case RE_TOK_ALTERNATIVE: + { + re_insert_value (re_ctx_p, alternative_offset, re_bytecode_size (re_ctx_p) - alternative_offset); + re_insert_opcode (re_ctx_p, + alternative_offset, + first_alternative ? RE_OP_ALTERNATIVE_START : RE_OP_ALTERNATIVE_NEXT); + + alternative_offset = re_bytecode_size (re_ctx_p); + first_alternative = false; + break; + } + case RE_TOK_ASSERT_START: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_LINE_START); + break; + } + case RE_TOK_ASSERT_END: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_LINE_END); + break; + } + case RE_TOK_ASSERT_WORD_BOUNDARY: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_WORD_BOUNDARY); + break; + } + case RE_TOK_ASSERT_NOT_WORD_BOUNDARY: + { + re_append_opcode (re_ctx_p, RE_OP_ASSERT_NOT_WORD_BOUNDARY); + break; + } + case RE_TOK_ASSERT_LOOKAHEAD: + { + const uint32_t start_capture_count = re_ctx_p->captures_count; + const bool is_negative = !!re_ctx_p->token.value; + + ecma_value_t result = re_parse_alternative (re_ctx_p, false); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (re_ctx_p->flags & RE_FLAG_UNICODE) + { + re_ctx_p->token.qmin = 1; + re_ctx_p->token.qmax = 1; + re_ctx_p->token.greedy = true; + } + else + { + re_parse_quantifier (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (re_check_quantifier (re_ctx_p))) + { + return ECMA_VALUE_ERROR; + } + } + + re_insert_assertion_lookahead (re_ctx_p, atom_offset, start_capture_count, is_negative); + break; + } + case RE_TOK_BACKREFERENCE: + { + const uint32_t backref_idx = re_ctx_p->token.value; + re_append_opcode (re_ctx_p, RE_OP_BACKREFERENCE); + re_append_value (re_ctx_p, backref_idx); + + if (re_ctx_p->token.qmin != 1 || re_ctx_p->token.qmax != 1) + { + const uint32_t group_idx = re_ctx_p->non_captures_count++; + re_insert_into_group (re_ctx_p, atom_offset, group_idx, re_ctx_p->captures_count, false); + } + + break; + } + case RE_TOK_CLASS_ESCAPE: + { + const ecma_class_escape_t escape = (ecma_class_escape_t) re_ctx_p->token.value; + re_append_opcode (re_ctx_p, RE_OP_CLASS_ESCAPE); + re_append_byte (re_ctx_p, (uint8_t) escape); + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + case RE_TOK_CHAR_CLASS: + { + ecma_value_t result = re_parse_char_class (re_ctx_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + case RE_TOK_END_GROUP: + { + if (expect_eof) + { + return ecma_raise_syntax_error (ECMA_ERR_UNMATCHED_CLOSE_BRACKET); + } + + if (!first_alternative) + { + re_insert_value (re_ctx_p, alternative_offset, re_bytecode_size (re_ctx_p) - alternative_offset); + re_insert_opcode (re_ctx_p, alternative_offset, RE_OP_ALTERNATIVE_NEXT); + } + + return ECMA_VALUE_EMPTY; + } + case RE_TOK_EOF: + { + if (!expect_eof) + { + return ecma_raise_syntax_error (ECMA_ERR_UNEXPECTED_END_OF_PATTERN); + } + + if (!first_alternative) + { + re_insert_value (re_ctx_p, alternative_offset, re_bytecode_size (re_ctx_p) - alternative_offset); + re_insert_opcode (re_ctx_p, alternative_offset, RE_OP_ALTERNATIVE_NEXT); + } + + re_append_opcode (re_ctx_p, RE_OP_EOF); + return ECMA_VALUE_EMPTY; + } + default: + { + JERRY_ASSERT (re_ctx_p->token.type == RE_TOK_CHAR); + + lit_code_point_t ch = re_ctx_p->token.value; + + if (ch <= LIT_UTF8_1_BYTE_CODE_POINT_MAX && (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) == 0) + { + re_append_opcode (re_ctx_p, RE_OP_BYTE); + re_append_byte (re_ctx_p, (uint8_t) ch); + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + + if (re_ctx_p->flags & RE_FLAG_IGNORE_CASE) + { + ch = ecma_regexp_canonicalize_char (ch, re_ctx_p->flags & RE_FLAG_UNICODE); + } + + re_append_opcode (re_ctx_p, RE_OP_CHAR); + re_append_char (re_ctx_p, ch); + + re_insert_atom_iterator (re_ctx_p, atom_offset); + break; + } + } + } + + return ECMA_VALUE_EMPTY; +} /* re_parse_alternative */ + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.h new file mode 100644 index 00000000..0c28edc3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-parser.h @@ -0,0 +1,59 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_PARSER_H +#define RE_PARSER_H + +#include "re-compiler-context.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * @} + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * Value used for infinite quantifier. + */ +#define RE_INFINITY UINT32_MAX + +/** + * Maximum decimal value of an octal escape + */ +#define RE_MAX_OCTAL_VALUE 0xff + +ecma_value_t re_parse_alternative (re_compiler_ctx_t *re_ctx_p, bool expect_eof); + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_PARSER_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-token.h b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-token.h new file mode 100644 index 00000000..ad3b5dfe --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/parser/regexp/re-token.h @@ -0,0 +1,74 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RE_TOKEN_H +#define RE_TOKEN_H + +#include "ecma-globals.h" + +#if JERRY_BUILTIN_REGEXP + +/** \addtogroup parser Parser + * @{ + * + * \addtogroup regexparser Regular expression + * @{ + * + * \addtogroup regexparser_parser Parser + * @{ + */ + +/** + * RegExp token type definitions + */ +typedef enum +{ + RE_TOK_EOF, /**< EOF */ + RE_TOK_BACKREFERENCE, /**< "\[0..9]" */ + RE_TOK_ALTERNATIVE, /**< "|" */ + RE_TOK_ASSERT_START, /**< "^" */ + RE_TOK_ASSERT_END, /**< "$" */ + RE_TOK_PERIOD, /**< "." */ + RE_TOK_START_CAPTURE_GROUP, /**< "(" */ + RE_TOK_START_NON_CAPTURE_GROUP, /**< "(?:" */ + RE_TOK_END_GROUP, /**< ")" */ + RE_TOK_ASSERT_LOOKAHEAD, /**< "(?=" */ + RE_TOK_ASSERT_WORD_BOUNDARY, /**< "\b" */ + RE_TOK_ASSERT_NOT_WORD_BOUNDARY, /**< "\B" */ + RE_TOK_CLASS_ESCAPE, /**< "\d \D \w \W \s \S" */ + RE_TOK_CHAR_CLASS, /**< "[ ]" */ + RE_TOK_CHAR, /**< any character */ +} re_token_type_t; + +/** + * RegExp token + */ +typedef struct +{ + uint32_t value; /**< value of the token */ + uint32_t qmin; /**< minimum number of token iterations */ + uint32_t qmax; /**< maximum number of token iterations */ + re_token_type_t type; /**< type of the token */ + bool greedy; /**< type of iteration */ +} re_token_t; + +/** + * @} + * @} + * @} + */ + +#endif /* JERRY_BUILTIN_REGEXP */ +#endif /* !RE_TOKEN_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/meson.build b/src/loaders/lottie/jerryscript/jerry-core/vm/meson.build new file mode 100644 index 00000000..b2621bea --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/meson.build @@ -0,0 +1,18 @@ +source_file = [ + 'opcodes.h', + 'vm-defines.h', + 'vm-stack.h', + 'vm.h', + 'opcodes-ecma-arithmetics.cpp', + 'opcodes-ecma-bitwise.cpp', + 'opcodes-ecma-relational-equality.cpp', + 'opcodes.cpp', + 'vm-stack.cpp', + 'vm-utils.cpp', + 'vm.cpp' +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.cpp new file mode 100644 index 00000000..d6503a40 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.cpp @@ -0,0 +1,337 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "jrt-libc-includes.h" +#include "opcodes.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Perform ECMA number arithmetic operation. + * + * The algorithm of the operation is following: + * leftNum = ToNumber (leftValue); + * rightNum = ToNumber (rightValue); + * result = leftNum ArithmeticOp rightNum; + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation */ + ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + + ecma_number_t right_number; + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (right_value, &right_number))) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + + switch (op) + { + case NUMBER_ARITHMETIC_SUBTRACTION: + { + result = left_number - right_number; + break; + } + case NUMBER_ARITHMETIC_MULTIPLICATION: + { + result = left_number * right_number; + break; + } + case NUMBER_ARITHMETIC_DIVISION: + { + result = left_number / right_number; + break; + } + case NUMBER_ARITHMETIC_REMAINDER: + { + if (ecma_number_is_nan (left_number) || ecma_number_is_nan (right_number) + || ecma_number_is_infinity (left_number) || ecma_number_is_zero (right_number)) + { + result = ecma_number_make_nan (); + break; + } + + if (ecma_number_is_infinity (right_number) + || (ecma_number_is_zero (left_number) && !ecma_number_is_zero (right_number))) + { + result = left_number; + break; + } + + result = ecma_number_remainder (left_number, right_number); + break; + } + case NUMBER_ARITHMETIC_EXPONENTIATION: + { + result = ecma_number_pow (left_number, right_number); + break; + } + } + + ret_value = ecma_make_number_value (result); +#if JERRY_BUILTIN_BIGINT + } + else + { + bool free_right_value; + right_value = ecma_bigint_get_bigint (right_value, &free_right_value); + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + ecma_free_value (left_value); + return right_value; + } + + switch (op) + { + case NUMBER_ARITHMETIC_SUBTRACTION: + { + ret_value = ecma_bigint_add_sub (left_value, right_value, false); + break; + } + case NUMBER_ARITHMETIC_MULTIPLICATION: + { + ret_value = ecma_bigint_mul (left_value, right_value); + break; + } + case NUMBER_ARITHMETIC_DIVISION: + { + ret_value = ecma_bigint_div_mod (left_value, right_value, false); + break; + } + case NUMBER_ARITHMETIC_REMAINDER: + { + ret_value = ecma_bigint_div_mod (left_value, right_value, true); + break; + } + case NUMBER_ARITHMETIC_EXPONENTIATION: + { + ret_value = ecma_bigint_pow (left_value, right_value); + break; + } + } + + ecma_free_value (left_value); + if (free_right_value) + { + ecma_free_value (right_value); + } + } +#endif /* JERRY_BUILTIN_BIGINT */ + return ret_value; +} /* do_number_arithmetic */ + +/** + * 'Addition' opcode handler. + * + * See also: ECMA-262 v5, 11.6.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_addition (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + bool free_left_value = false; + bool free_right_value = false; + + if (ecma_is_value_object (left_value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (left_value); + left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); + free_left_value = true; + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + } + + if (ecma_is_value_object (right_value)) + { + ecma_object_t *obj_p = ecma_get_object_from_value (right_value); + right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); + free_right_value = true; + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + if (free_left_value) + { + ecma_free_value (left_value); + } + return right_value; + } + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + if (ecma_is_value_string (left_value) || ecma_is_value_string (right_value)) + { + ecma_string_t *string1_p = ecma_op_to_string (left_value); + + if (JERRY_UNLIKELY (string1_p == NULL)) + { + if (free_left_value) + { + ecma_free_value (left_value); + } + if (free_right_value) + { + ecma_free_value (right_value); + } + return ECMA_VALUE_ERROR; + } + + ecma_string_t *string2_p = ecma_op_to_string (right_value); + + if (JERRY_UNLIKELY (string2_p == NULL)) + { + if (free_right_value) + { + ecma_free_value (right_value); + } + if (free_left_value) + { + ecma_free_value (left_value); + } + ecma_deref_ecma_string (string1_p); + return ECMA_VALUE_ERROR; + } + + string1_p = ecma_concat_ecma_strings (string1_p, string2_p); + ret_value = ecma_make_string_value (string1_p); + + ecma_deref_ecma_string (string2_p); + } +#if JERRY_BUILTIN_BIGINT + else if (JERRY_UNLIKELY (ecma_is_value_bigint (left_value)) && JERRY_UNLIKELY (ecma_is_value_bigint (right_value))) + { + ret_value = ecma_bigint_add_sub (left_value, right_value, true); + } +#endif /* JERRY_BUILTIN_BIGINT */ + else + { + ecma_number_t num_left; + ecma_number_t num_right; + if (!ECMA_IS_VALUE_ERROR (ecma_op_to_number (left_value, &num_left)) + && !ECMA_IS_VALUE_ERROR (ecma_op_to_number (right_value, &num_right))) + { + ret_value = ecma_make_number_value (num_left + num_right); + } + else + { + ret_value = ECMA_VALUE_ERROR; + } + } + + if (free_left_value) + { + ecma_free_value (left_value); + } + + if (free_right_value) + { + ecma_free_value (right_value); + } + + return ret_value; +} /* opfunc_addition */ + +/** + * Unary operation opcode handler. + * + * See also: ECMA-262 v5, 11.4, 11.4.6, 11.4.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_unary_operation (ecma_value_t left_value, /**< left value */ + bool is_plus) /**< unary plus flag */ +{ + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) + { + return ecma_make_number_value (is_plus ? left_number : -left_number); + } + + ecma_value_t ret_value; + + if (is_plus) + { + ret_value = ecma_raise_type_error (ECMA_ERR_UNARY_PLUS_IS_NOT_ALLOWED_FOR_BIGINTS); + } + else + { + ret_value = left_value; + + if (left_value != ECMA_BIGINT_ZERO) + { + ret_value = ecma_bigint_negate (ecma_get_extended_primitive_from_value (left_value)); + } + } + + ecma_free_value (left_value); + return ret_value; +#else /* !JERRY_BUILTIN_BIGINT */ + return ecma_make_number_value (is_plus ? left_number : -left_number); +#endif /* JERRY_BUILTIN_BIGINT */ +} /* opfunc_unary_operation */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.cpp new file mode 100644 index 00000000..3653f7b1 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.cpp @@ -0,0 +1,212 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-alloc.h" +#include "ecma-bigint.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "opcodes.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Perform ECMA number logic operation. + * + * The algorithm of the operation is following: + * leftNum = ToNumber (leftValue); + * rightNum = ToNumber (rightValue); + * result = leftNum BitwiseLogicOp rightNum; + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic operation */ + ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (left_value)) + { + return left_value; + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + ecma_number_t right_number; + + if (ECMA_IS_VALUE_ERROR (ecma_op_to_number (right_value, &right_number))) + { + return ECMA_VALUE_ERROR; + } + + ecma_number_t result = ECMA_NUMBER_ZERO; + uint32_t right_uint32 = ecma_number_to_uint32 (right_number); + + switch (op) + { + case NUMBER_BITWISE_LOGIC_AND: + { + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) ((int32_t) (left_uint32 & right_uint32)); + break; + } + case NUMBER_BITWISE_LOGIC_OR: + { + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) ((int32_t) (left_uint32 | right_uint32)); + break; + } + case NUMBER_BITWISE_LOGIC_XOR: + { + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) ((int32_t) (left_uint32 ^ right_uint32)); + break; + } + case NUMBER_BITWISE_SHIFT_LEFT: + { + result = (ecma_number_t) ((int32_t) ((uint32_t) ecma_number_to_int32 (left_number) << (right_uint32 & 0x1F))); + break; + } + case NUMBER_BITWISE_SHIFT_RIGHT: + { + result = (ecma_number_t) (ecma_number_to_int32 (left_number) >> (right_uint32 & 0x1F)); + break; + } + default: + { + JERRY_ASSERT (op == NUMBER_BITWISE_SHIFT_URIGHT); + + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); + result = (ecma_number_t) (left_uint32 >> (right_uint32 & 0x1F)); + break; + } + } + + ret_value = ecma_make_number_value (result); + +#if JERRY_BUILTIN_BIGINT + } + else + { + bool free_right_value; + right_value = ecma_bigint_get_bigint (right_value, &free_right_value); + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + ecma_free_value (left_value); + return right_value; + } + + switch (op) + { + case NUMBER_BITWISE_LOGIC_AND: + { + ret_value = ecma_bigint_and (left_value, right_value); + break; + } + case NUMBER_BITWISE_LOGIC_OR: + { + ret_value = ecma_bigint_or (left_value, right_value); + break; + } + case NUMBER_BITWISE_LOGIC_XOR: + { + ret_value = ecma_bigint_xor (left_value, right_value); + break; + } + case NUMBER_BITWISE_SHIFT_LEFT: + { + ret_value = ecma_bigint_shift (left_value, right_value, true); + break; + } + case NUMBER_BITWISE_SHIFT_RIGHT: + { + ret_value = ecma_bigint_shift (left_value, right_value, false); + break; + } + default: + { + JERRY_ASSERT (op == NUMBER_BITWISE_SHIFT_URIGHT); + + ret_value = ecma_raise_type_error (ECMA_ERR_UNSIGNED_RIGHT_SHIFT_IS_NOT_ALLOWED_FOR_BIGINTS); + break; + } + } + + ecma_free_value (left_value); + if (free_right_value) + { + ecma_free_value (right_value); + } + } +#endif /* JERRY_BUILTIN_BIGINT */ + + return ret_value; +} /* do_number_bitwise_logic */ + +/** + * Perform ECMA number bitwise not operation. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +do_number_bitwise_not (ecma_value_t value) /**< value */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value)); + + ecma_number_t number; + value = ecma_op_to_numeric (value, &number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } + +#if JERRY_BUILTIN_BIGINT + if (JERRY_LIKELY (!ecma_is_value_bigint (value))) + { +#endif /* JERRY_BUILTIN_BIGINT */ + return ecma_make_number_value ((ecma_number_t) ((int32_t) ~ecma_number_to_uint32 (number))); +#if JERRY_BUILTIN_BIGINT + } + + ecma_value_t ret_value = ecma_bigint_unary (value, ECMA_BIGINT_UNARY_BITWISE_NOT); + ecma_free_value (value); + return ret_value; +#endif /* JERRY_BUILTIN_BIGINT */ +} /* do_number_bitwise_not */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-relational-equality.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-relational-equality.cpp new file mode 100644 index 00000000..b3602adf --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes-ecma-relational-equality.cpp @@ -0,0 +1,173 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" + +#include "opcodes.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Equality opcode handler. + * + * See also: ECMA-262 v5, 11.9.1, 11.9.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_equality (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + ecma_value_t compare_result = ecma_op_abstract_equality_compare (left_value, right_value); + + JERRY_ASSERT (ecma_is_value_boolean (compare_result) || ECMA_IS_VALUE_ERROR (compare_result)); + + return compare_result; +} /* opfunc_equality */ + +/** + * Relation opcode handler. + * + * See also: ECMA-262 v5, 11.8.1, 11.8.2, 11.8.3, 11.8.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_relation (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value, /**< right value */ + bool left_first, /**< 'LeftFirst' flag */ + bool is_invert) /**< is invert */ +{ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, left_first); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + return ret_value; + } + + if (ecma_is_value_undefined (ret_value)) + { + ret_value = ECMA_VALUE_FALSE; + } + else + { + JERRY_ASSERT (ecma_is_value_boolean (ret_value)); + + if (is_invert) + { + ret_value = ecma_invert_boolean_value (ret_value); + } + } + + return ret_value; +} /* opfunc_relation */ + +/** + * 'instanceof' opcode handler. + * + * See also: ECMA-262 v5, 11.8.6 + * + * @return ecma value + * returned value must be freed with ecma_free_value. + */ +ecma_value_t +opfunc_instanceof (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + if (!ecma_is_value_object (right_value)) + { + return ecma_raise_type_error (ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT); + } + + ecma_value_t has_instance_method = ecma_op_get_method_by_symbol_id (right_value, LIT_GLOBAL_SYMBOL_HAS_INSTANCE); + if (ECMA_IS_VALUE_ERROR (has_instance_method)) + { + return has_instance_method; + } + + if (JERRY_UNLIKELY (!ecma_is_value_undefined (has_instance_method))) + { + ecma_object_t *method_obj_p = ecma_get_object_from_value (has_instance_method); + ecma_value_t has_instance_result = ecma_op_function_call (method_obj_p, right_value, &left_value, 1); + + ecma_free_value (has_instance_method); + + if (ECMA_IS_VALUE_ERROR (has_instance_result)) + { + return has_instance_result; + } + + bool has_instance = ecma_op_to_boolean (has_instance_result); + ecma_free_value (has_instance_result); + + return ecma_make_boolean_value (has_instance); + } + + ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); + return ecma_op_object_has_instance (right_value_obj_p, left_value); +} /* opfunc_instanceof */ + +/** + * 'in' opcode handler. + * + * See also: + * * ECMA-262 v5, 11.8.7 + * * ECAM-262 v6, 12.9.3 + * + * @return ecma value + * returned value must be freed with ecma_free_value. + */ +ecma_value_t +opfunc_in (ecma_value_t left_value, /**< left value */ + ecma_value_t right_value) /**< right value */ +{ + if (!ecma_is_value_object (right_value)) + { + return ecma_raise_type_error (ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT); + } + + ecma_string_t *property_name_p = ecma_op_to_property_key (left_value); + + if (JERRY_UNLIKELY (property_name_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); + ecma_value_t result = ecma_op_object_has_property (right_value_obj_p, property_name_p); + ecma_deref_ecma_string (property_name_p); + return result; +} /* opfunc_in */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.cpp new file mode 100644 index 00000000..9ce78f91 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.cpp @@ -0,0 +1,2302 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "opcodes.h" + +#include "ecma-alloc.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-conversion.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-proxy-object.h" + +#include "jcontext.h" +#include "vm-defines.h" +#include "vm-stack.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * 'typeof' opcode handler. + * + * See also: ECMA-262 v5, 11.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +opfunc_typeof (ecma_value_t left_value) /**< left value */ +{ + return ecma_make_magic_string_value (ecma_get_typeof_lit_id (left_value)); +} /* opfunc_typeof */ + +/** + * Update data property for object literals. + */ +void +opfunc_set_data_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *prop_name_p, /**< data property name */ + ecma_value_t value) /**< new value */ +{ + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + + ecma_property_t *property_p = ecma_find_named_property (object_p, prop_name_p); + ecma_property_value_t *prop_value_p; + + if (property_p == NULL) + { + prop_value_p = + ecma_create_named_data_property (object_p, prop_name_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + } + else + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, + ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp); + jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + + *property_p |= ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_WRITABLE; + prop_value_p->value = ecma_copy_value_if_not_object (value); + return; + } + } + + ecma_named_data_property_assign_value (object_p, prop_value_p, value); +} /* opfunc_set_data_property */ + +/** + * Update getter or setter for object literals. + */ +void +opfunc_set_accessor (bool is_getter, /**< is getter accessor */ + ecma_value_t object, /**< object value */ + ecma_string_t *accessor_name_p, /**< accessor name */ + ecma_value_t accessor) /**< accessor value */ +{ + ecma_object_t *object_p = ecma_get_object_from_value (object); + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + + ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p); + ecma_object_t *accessor_p = ecma_get_object_from_value (accessor); + + ecma_object_t *getter_func_p = NULL; + ecma_object_t *setter_func_p = NULL; + + if (is_getter) + { + getter_func_p = accessor_p; + } + else + { + setter_func_p = accessor_p; + } + + if (property_p == NULL) + { + ecma_create_named_accessor_property (object_p, + accessor_name_p, + getter_func_p, + setter_func_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE, + NULL); + } + else + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (*property_p & ECMA_PROPERTY_FLAG_DATA) + { +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p; + getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ + + ecma_free_value_if_not_object (prop_value_p->value); + *property_p = (uint8_t) (*property_p & ~(ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_WRITABLE)); + +#if JERRY_CPOINTER_32_BIT + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, getter_func_p); + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, setter_func_p); + ECMA_SET_NON_NULL_POINTER (prop_value_p->getter_setter_pair_cp, getter_setter_pair_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.getter_cp, getter_func_p); + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_cp, setter_func_p); +#endif /* JERRY_CPOINTER_32_BIT */ + return; + } + + if (is_getter) + { + ecma_set_named_accessor_property_getter (object_p, prop_value_p, accessor_p); + } + else + { + ecma_set_named_accessor_property_setter (object_p, prop_value_p, accessor_p); + } + } +} /* opfunc_set_accessor */ + +/** + * Deletes an object property. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +vm_op_delete_prop (ecma_value_t object, /**< base object */ + ecma_value_t property, /**< property name */ + bool is_strict) /**< strict mode */ +{ + if (!ecma_op_require_object_coercible (object)) + { + return ECMA_VALUE_ERROR; + } + + ecma_string_t *name_string_p = ecma_op_to_property_key (property); + + if (JERRY_UNLIKELY (name_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t obj_value = ecma_op_to_object (object); + /* The ecma_op_require_object_coercible call already checked the op_to_object error cases. */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (obj_value)); + JERRY_ASSERT (ecma_is_value_object (obj_value)); + ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + ecma_value_t delete_op_ret = ecma_op_object_delete (obj_p, name_string_p, is_strict); + JERRY_ASSERT (ecma_is_value_boolean (delete_op_ret) || ECMA_IS_VALUE_ERROR (delete_op_ret)); + ecma_deref_object (obj_p); + ecma_deref_ecma_string (name_string_p); + + if (is_strict && ecma_is_value_false (delete_op_ret)) + { + return ecma_raise_type_error (ECMA_ERR_OPERATOR_DELETE_RETURNED_FALSE_IN_STRICT_MODE); + } + + return delete_op_ret; +} /* vm_op_delete_prop */ + +/** + * Deletes a variable. + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +vm_op_delete_var (ecma_value_t name_literal, /**< name literal */ + ecma_object_t *lex_env_p) /**< lexical environment */ +{ + ecma_value_t completion_value = ECMA_VALUE_EMPTY; + + ecma_string_t *var_name_str_p = ecma_get_string_from_value (name_literal); + + ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p); + +#if JERRY_BUILTIN_PROXY + if (JERRY_UNLIKELY (ref_base_lex_env_p == ECMA_OBJECT_POINTER_ERROR)) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ref_base_lex_env_p == NULL) + { + completion_value = ECMA_VALUE_TRUE; + } + else + { + JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p)); + + completion_value = ecma_op_delete_binding (ref_base_lex_env_p, var_name_str_p); + } + + return completion_value; +} /* vm_op_delete_var */ + +/** + * 'for-in' opcode handler + * + * Note: from ES2015 (ES6) the for-in can trigger error when + * the property names are not available (ex.: via Proxy ownKeys). + * In these cases an error must be returned. + * + * This error is returned as the `result_obj_p` and the + * function's return value is NULL. + * + * See also: + * ECMA-262 v5, 12.6.4 + * + * @return - chain list of property names + * - In case of error: NULL is returned and the `result_obj_p` + * must be checked. + */ +ecma_collection_t * +opfunc_for_in (ecma_value_t iterable_value, /**< ideally an iterable value */ + ecma_value_t *result_obj_p) /**< expression object */ +{ + /* 3. */ + if (ecma_is_value_undefined (iterable_value) || ecma_is_value_null (iterable_value)) + { + return NULL; + } + + /* 4. */ + ecma_value_t obj_expr_value = ecma_op_to_object (iterable_value); + /* ecma_op_to_object will only raise error on null/undefined values but those are handled above. */ + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (obj_expr_value)); + ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value); + ecma_collection_t *prop_names_p = ecma_op_object_enumerate (obj_p); + + if (JERRY_UNLIKELY (prop_names_p == NULL)) + { + ecma_deref_object (obj_p); + *result_obj_p = ECMA_VALUE_ERROR; + return NULL; + } + + if (prop_names_p->item_count != 0) + { + *result_obj_p = ecma_make_object_value (obj_p); + return prop_names_p; + } + + ecma_deref_object (obj_p); + ecma_collection_destroy (prop_names_p); + + return NULL; +} /* opfunc_for_in */ + +/** + * 'VM_OC_APPEND_ARRAY' opcode handler specialized for spread objects + * + * @return ECMA_VALUE_ERROR - if the operation failed + * ECMA_VALUE_EMPTY, otherwise + */ +static ecma_value_t JERRY_ATTR_NOINLINE +opfunc_append_to_spread_array (ecma_value_t *stack_top_p, /**< current stack top */ + uint16_t values_length) /**< number of elements to set */ +{ + JERRY_ASSERT (!(values_length & OPFUNC_HAS_SPREAD_ELEMENT)); + + ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; + uint32_t old_length = ext_array_obj_p->u.array.length; + + for (uint32_t i = 0, idx = old_length; i < values_length; i++, idx++) + { + if (ecma_is_value_array_hole (stack_top_p[i])) + { + continue; + } + + if (stack_top_p[i] == ECMA_VALUE_SPREAD_ELEMENT) + { + i++; + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_value_t spread_value = stack_top_p[i]; + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (!ECMA_IS_VALUE_ERROR (iterator)) + { + while (true) + { + ecma_value_t next_value = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + break; + } + + if (ecma_is_value_false (next_value)) + { + idx--; + ret_value = ECMA_VALUE_EMPTY; + break; + } + + ecma_value_t value = ecma_op_iterator_value (next_value); + + ecma_free_value (next_value); + + if (ECMA_IS_VALUE_ERROR (value)) + { + break; + } + + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, + idx++, + value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + + JERRY_ASSERT (ecma_is_value_true (put_comp)); + ecma_free_value (value); + } + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_free_value (spread_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + for (uint32_t k = i + 1; k < values_length; k++) + { + ecma_free_value (stack_top_p[k]); + } + + return ret_value; + } + } + else + { + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, + idx, + stack_top_p[i], + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (put_comp)); + ecma_free_value (stack_top_p[i]); + } + } + + return ECMA_VALUE_EMPTY; +} /* opfunc_append_to_spread_array */ + +/** + * Spread function call/construct arguments into an ecma-collection + * + * @return NULL - if the operation failed + * pointer to the ecma-collection with the spreaded arguments, otherwise + */ +JERRY_ATTR_NOINLINE ecma_collection_t * +opfunc_spread_arguments (ecma_value_t *stack_top_p, /**< pointer to the current stack top */ + uint8_t arguments_list_len) /**< number of arguments */ +{ + ecma_collection_t *buff_p = ecma_new_collection (); + + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_value_t arg = *stack_top_p++; + + if (arg != ECMA_VALUE_SPREAD_ELEMENT) + { + ecma_collection_push_back (buff_p, arg); + continue; + } + + ecma_value_t ret_value = ECMA_VALUE_ERROR; + ecma_value_t spread_value = *stack_top_p++; + i++; + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + if (!ECMA_IS_VALUE_ERROR (iterator)) + { + while (true) + { + ecma_value_t next_value = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + break; + } + + if (ecma_is_value_false (next_value)) + { + ret_value = ECMA_VALUE_EMPTY; + break; + } + + ecma_value_t value = ecma_op_iterator_value (next_value); + + ecma_free_value (next_value); + + if (ECMA_IS_VALUE_ERROR (value)) + { + break; + } + + ecma_collection_push_back (buff_p, value); + } + } + + ecma_free_value (iterator); + ecma_free_value (next_method); + ecma_free_value (spread_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + for (uint32_t k = i + 1; k < arguments_list_len; k++) + { + ecma_free_value (*stack_top_p++); + } + + ecma_collection_free (buff_p); + buff_p = NULL; + break; + } + } + + return buff_p; +} /* opfunc_spread_arguments */ + +/** + * 'VM_OC_APPEND_ARRAY' opcode handler, for setting array object properties + * + * @return ECMA_VALUE_ERROR - if the operation failed + * ECMA_VALUE_EMPTY, otherwise + */ +ecma_value_t JERRY_ATTR_NOINLINE +opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */ + uint16_t values_length) /**< number of elements to set + * with potential OPFUNC_HAS_SPREAD_ELEMENT flag */ +{ + if (values_length >= OPFUNC_HAS_SPREAD_ELEMENT) + { + return opfunc_append_to_spread_array (stack_top_p, (uint16_t) (values_length & ~OPFUNC_HAS_SPREAD_ELEMENT)); + } + + ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; + uint32_t old_length = ext_array_obj_p->u.array.length; + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_array_obj_p))) + { + uint32_t filled_holes = 0; + ecma_value_t *values_p = ecma_fast_array_extend (array_obj_p, old_length + values_length); + + for (uint32_t i = 0; i < values_length; i++) + { + values_p[old_length + i] = stack_top_p[i]; + + if (!ecma_is_value_array_hole (stack_top_p[i])) + { + filled_holes++; + + ecma_deref_if_object (stack_top_p[i]); + } + } + + ext_array_obj_p->u.array.length_prop_and_hole_count -= filled_holes * ECMA_FAST_ARRAY_HOLE_ONE; + + if (JERRY_UNLIKELY ((values_length - filled_holes) > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT)) + { + ecma_fast_array_convert_to_normal (array_obj_p); + } + } + else + { + for (uint32_t i = 0; i < values_length; i++) + { + if (!ecma_is_value_array_hole (stack_top_p[i])) + { + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (old_length + i); + + ecma_property_value_t *prop_value_p; + + prop_value_p = ecma_create_named_data_property (array_obj_p, + index_str_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + ecma_deref_ecma_string (index_str_p); + prop_value_p->value = stack_top_p[i]; + ecma_deref_if_object (stack_top_p[i]); + } + } + ext_array_obj_p->u.array.length = old_length + values_length; + } + + return ECMA_VALUE_EMPTY; +} /* opfunc_append_array */ + +/** + * Create an executable object using the current frame context + * + * @return executable object + */ +vm_executable_object_t * +opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + vm_create_executable_object_type_t type) /**< executable object type */ +{ + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; + size_t size, register_end; + + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_header_p); + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + register_end = (size_t) args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + register_end = (size_t) args_p->register_end; + size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t); + } + + size_t total_size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t)); + + ecma_object_t *proto_p = NULL; + /* Async function objects are not accessible, so their class_id is not relevant. */ + uint8_t class_type = ECMA_OBJECT_CLASS_GENERATOR; + + if (type == VM_CREATE_EXECUTABLE_OBJECT_GENERATOR) + { + ecma_builtin_id_t default_proto_id = ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE; + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) + { + default_proto_id = ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE; + class_type = ECMA_OBJECT_CLASS_ASYNC_GENERATOR; + } + + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); + proto_p = ecma_op_get_prototype_from_constructor (frame_ctx_p->shared_p->function_object_p, default_proto_id); + } + + ecma_object_t *object_p = ecma_create_object (proto_p, total_size, ECMA_OBJECT_TYPE_CLASS); + + vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; + + if (type == VM_CREATE_EXECUTABLE_OBJECT_GENERATOR) + { + ecma_deref_object (proto_p); + } + + executable_object_p->extended_object.u.cls.type = class_type; + executable_object_p->extended_object.u.cls.u2.executable_obj_flags = 0; + ECMA_SET_INTERNAL_VALUE_ANY_POINTER (executable_object_p->extended_object.u.cls.u3.head, NULL); + executable_object_p->iterator = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (!(frame_ctx_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL)); + + /* Copy shared data and frame context. */ + vm_frame_ctx_shared_t *new_shared_p = &(executable_object_p->shared); + *new_shared_p = *(frame_ctx_p->shared_p); + new_shared_p->status_flags &= (uint32_t) ~VM_FRAME_CTX_SHARED_HAS_ARG_LIST; + new_shared_p->status_flags |= VM_FRAME_CTX_SHARED_EXECUTABLE; + + vm_frame_ctx_t *new_frame_ctx_p = &(executable_object_p->frame_ctx); + *new_frame_ctx_p = *frame_ctx_p; + new_frame_ctx_p->shared_p = new_shared_p; + + /* The old register values are discarded. */ + ecma_value_t *new_registers_p = VM_GET_REGISTERS (new_frame_ctx_p); + memcpy (new_registers_p, VM_GET_REGISTERS (frame_ctx_p), size); + + size_t stack_top = (size_t) (frame_ctx_p->stack_top_p - VM_GET_REGISTERS (frame_ctx_p)); + ecma_value_t *new_stack_top_p = new_registers_p + stack_top; + + new_frame_ctx_p->stack_top_p = new_stack_top_p; + + /* Initial state is "not running", so all object references are released. */ + + if (frame_ctx_p->context_depth > 0) + { + JERRY_ASSERT (type != VM_CREATE_EXECUTABLE_OBJECT_GENERATOR); + + ecma_value_t *register_end_p = new_registers_p + register_end; + + JERRY_ASSERT (register_end_p <= new_stack_top_p); + + while (new_registers_p < register_end_p) + { + ecma_deref_if_object (*new_registers_p++); + } + + vm_ref_lex_env_chain (frame_ctx_p->lex_env_p, frame_ctx_p->context_depth, new_registers_p, false); + + new_registers_p += frame_ctx_p->context_depth; + + JERRY_ASSERT (new_registers_p <= new_stack_top_p); + } + + while (new_registers_p < new_stack_top_p) + { + ecma_deref_if_object (*new_registers_p++); + } + + JERRY_ASSERT (*VM_GET_EXECUTABLE_ITERATOR (new_frame_ctx_p) == ECMA_VALUE_UNDEFINED); + + new_frame_ctx_p->this_binding = ecma_copy_value_if_not_object (new_frame_ctx_p->this_binding); + + JERRY_CONTEXT (vm_top_context_p) = new_frame_ctx_p->prev_context_p; + + return executable_object_p; +} /* opfunc_create_executable_object */ + +/** + * Byte code which resumes an executable object with throw + */ +const uint8_t opfunc_resume_executable_object_with_throw[1] = { CBC_THROW }; + +/** + * Byte code which resumes an executable object with return + */ +const uint8_t opfunc_resume_executable_object_with_return[2] = { CBC_EXT_OPCODE, CBC_EXT_RETURN }; + +/** + * Resume the execution of an inactive executable object + * + * @return value provided by the execution + */ +ecma_value_t +opfunc_resume_executable_object (vm_executable_object_t *executable_object_p, /**< executable object */ + ecma_value_t value) /**< value pushed onto the stack (takes the reference) */ +{ + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; + ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + ecma_value_t *register_end_p; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + register_end_p = register_p + args_p->register_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + register_end_p = register_p + args_p->register_end; + } + + ecma_value_t *stack_top_p = executable_object_p->frame_ctx.stack_top_p; + + if (value != ECMA_VALUE_EMPTY) + { + *stack_top_p = value; + executable_object_p->frame_ctx.stack_top_p = stack_top_p + 1; + } + + if (executable_object_p->frame_ctx.context_depth > 0) + { + while (register_p < register_end_p) + { + ecma_ref_if_object (*register_p++); + } + + vm_ref_lex_env_chain (executable_object_p->frame_ctx.lex_env_p, + executable_object_p->frame_ctx.context_depth, + register_p, + true); + + register_p += executable_object_p->frame_ctx.context_depth; + } + + while (register_p < stack_top_p) + { + ecma_ref_if_object (*register_p++); + } + + ecma_ref_if_object (executable_object_p->iterator); + + JERRY_ASSERT (ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p)); + + executable_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_RUNNING; + + executable_object_p->frame_ctx.prev_context_p = JERRY_CONTEXT (vm_top_context_p); + JERRY_CONTEXT (vm_top_context_p) = &executable_object_p->frame_ctx; + + /* inside the generators the "new.target" is always "undefined" as it can't be invoked with "new" */ + ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = NULL; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = ecma_op_function_get_realm (bytecode_header_p); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t result = vm_execute (&executable_object_p->frame_ctx); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + JERRY_CONTEXT (current_new_target_p) = old_new_target; + executable_object_p->extended_object.u.cls.u2.executable_obj_flags &= (uint8_t) ~ECMA_EXECUTABLE_OBJECT_RUNNING; + + if (executable_object_p->frame_ctx.call_operation != VM_EXEC_RETURN) + { + JERRY_ASSERT (executable_object_p->frame_ctx.call_operation == VM_NO_EXEC_OP); + + /* All resources are released. */ + executable_object_p->extended_object.u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_COMPLETED; + return result; + } + + JERRY_CONTEXT (vm_top_context_p) = executable_object_p->frame_ctx.prev_context_p; + + register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); + stack_top_p = executable_object_p->frame_ctx.stack_top_p; + + if (executable_object_p->frame_ctx.context_depth > 0) + { + while (register_p < register_end_p) + { + ecma_deref_if_object (*register_p++); + } + + vm_ref_lex_env_chain (executable_object_p->frame_ctx.lex_env_p, + executable_object_p->frame_ctx.context_depth, + register_p, + false); + + register_p += executable_object_p->frame_ctx.context_depth; + } + + while (register_p < stack_top_p) + { + ecma_deref_if_object (*register_p++); + } + + ecma_deref_if_object (executable_object_p->iterator); + + return result; +} /* opfunc_resume_executable_object */ + +/** + * Fulfill the next promise of the async generator with the value + */ +void +opfunc_async_generator_yield (ecma_extended_object_t *async_generator_object_p, /**< async generator object */ + ecma_value_t value) /**< value (takes the reference) */ +{ + ecma_async_generator_task_t *task_p; + task_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_async_generator_task_t, async_generator_object_p->u.cls.u3.head); + + ecma_value_t iter_result = ecma_create_iter_result_object (value, ECMA_VALUE_FALSE); + ecma_fulfill_promise (task_p->promise, iter_result); + + ecma_free_value (iter_result); + ecma_free_value (value); + + ecma_value_t next = task_p->next; + async_generator_object_p->u.cls.u3.head = next; + + JERRY_ASSERT (task_p->operation_value == ECMA_VALUE_UNDEFINED); + jmem_heap_free_block (task_p, sizeof (ecma_async_generator_task_t)); + + if (!ECMA_IS_INTERNAL_VALUE_NULL (next)) + { + ecma_value_t executable_object = ecma_make_object_value ((ecma_object_t *) async_generator_object_p); + ecma_enqueue_promise_async_generator_job (executable_object); + } +} /* opfunc_async_generator_yield */ + +/** + * Creates a new executable object and awaits for the value + * + * Note: + * extra_flags can be used to set additional extra_info flags + * + * @return a new Promise object on success, error otherwise + */ +ecma_value_t +opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t value, /**< awaited value (takes reference) */ + uint16_t extra_flags) /**< extra flags */ +{ + JERRY_ASSERT ( + CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC + || (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_ARROW)); + + ecma_object_t *promise_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE); + ecma_value_t result = ecma_promise_reject_or_resolve (ecma_make_object_value (promise_p), value, true); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + vm_executable_object_t *executable_object_p; + executable_object_p = opfunc_create_executable_object (frame_ctx_p, VM_CREATE_EXECUTABLE_OBJECT_ASYNC); + + executable_object_p->extended_object.u.cls.u2.executable_obj_flags |= extra_flags; + + ecma_promise_async_then (result, ecma_make_object_value ((ecma_object_t *) executable_object_p)); + ecma_deref_object ((ecma_object_t *) executable_object_p); + ecma_free_value (result); + + result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, promise_p); + + JERRY_ASSERT (ecma_is_value_object (result)); + executable_object_p->iterator = result; + + return result; +} /* opfunc_async_create_and_await */ + +/** + * PrivateMethodOrAccessorAdd abstact operation. + * + * See also: ECMAScript v12, 7.3.29. + * + * @return ECMA_VALUE_ERROR - initialization fails + * ECMA_VALUE_UNDEFINED - otherwise + */ +static ecma_value_t +opfunc_private_method_or_accessor_add (ecma_object_t *class_object_p, /**< the function itself */ + ecma_object_t *this_obj_p, /**< this object */ + uint32_t static_flag) /**< static_flag */ +{ + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p == NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + uint32_t prop_desc = *current_p++; + ecma_private_property_kind_t kind = ECMA_PRIVATE_PROPERTY_KIND (prop_desc); + + if ((prop_desc & ECMA_PRIVATE_PROPERTY_STATIC_FLAG) != static_flag || kind == ECMA_PRIVATE_FIELD) + { + current_p += 2; + continue; + } + + ecma_string_t *prop_name_p = ecma_get_symbol_from_value (*current_p++); + ecma_value_t method = *current_p++; + + JERRY_ASSERT (prop_name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD); + + prop_p = ecma_find_named_property (this_obj_p, prop_name_p); + ecma_object_t *method_p = ecma_get_object_from_value (method); + + if (kind == ECMA_PRIVATE_METHOD) + { + if (prop_p != NULL) + { + return ecma_raise_type_error (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE); + } + + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (this_obj_p, prop_name_p, ECMA_PROPERTY_FIXED, NULL); + prop_value_p->value = method; + continue; + } + + if (prop_p == NULL) + { + ecma_object_t *getter_p = (kind == ECMA_PRIVATE_GETTER) ? method_p : NULL; + ecma_object_t *setter_p = (kind == ECMA_PRIVATE_SETTER) ? method_p : NULL; + ecma_create_named_accessor_property (this_obj_p, prop_name_p, getter_p, setter_p, ECMA_PROPERTY_FIXED, NULL); + continue; + } + + ecma_property_value_t *accessor_objs_p = ECMA_PROPERTY_VALUE_PTR (prop_p); + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p); + + if (kind == ECMA_PRIVATE_GETTER) + { + ECMA_SET_POINTER (get_set_pair_p->getter_cp, method_p); + } + else + { + JERRY_ASSERT (kind == ECMA_PRIVATE_SETTER); + ECMA_SET_POINTER (get_set_pair_p->setter_cp, method_p); + } + } + + return ECMA_VALUE_UNDEFINED; +} /* opfunc_private_method_or_accessor_add */ + +/** + * DefineField abstract operation. + * + * See also: ECMAScript v12, 7.3.32. + * + * @return ECMA_VALUE_ERROR - operation fails + * ECMA_VALUE_{TRUE/FALSE} - otherwise + */ +ecma_value_t +opfunc_define_field (ecma_value_t base, /**< base */ + ecma_value_t property, /**< property */ + ecma_value_t value) /**< value */ +{ + ecma_string_t *property_key_p = ecma_op_to_property_key (property); + + JERRY_ASSERT (property_key_p != NULL); + ecma_object_t *obj_p = ecma_get_object_from_value (base); + ecma_property_descriptor_t desc = ecma_make_empty_property_descriptor (); + desc.value = value; + desc.flags = (JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE + | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED + | JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_SHOULD_THROW); + + ecma_value_t result = ecma_op_object_define_own_property (obj_p, property_key_p, &desc); + ecma_deref_ecma_string (property_key_p); + + return result; +} /* opfunc_define_field */ + +/** + * Initialize class fields. + * + * @return ECMA_VALUE_ERROR - initialization fails + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +opfunc_init_class_fields (ecma_object_t *class_object_p, /**< the function itself */ + ecma_value_t this_val) /**< this_arg of the function */ +{ + JERRY_ASSERT (ecma_is_value_object (this_val)); + ecma_object_t *this_obj_p = ecma_get_object_from_value (this_val); + + ecma_value_t result = opfunc_private_method_or_accessor_add (class_object_p, this_obj_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT); + ecma_property_t *property_p = ecma_find_named_property (class_object_p, name_p); + + if (property_p == NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + vm_frame_ctx_shared_class_fields_t shared_class_fields; + shared_class_fields.header.status_flags = VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS; + shared_class_fields.computed_class_fields_p = NULL; + + name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_property_t *class_field_property_p = ecma_find_named_property (class_object_p, name_p); + + if (class_field_property_p != NULL) + { + ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (class_field_property_p)->value; + shared_class_fields.computed_class_fields_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + } + + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + JERRY_ASSERT (ecma_op_is_callable (property_value_p->value)); + + ecma_extended_object_t *ext_function_p; + ext_function_p = (ecma_extended_object_t *) ecma_get_object_from_value (property_value_p->value); + shared_class_fields.header.bytecode_header_p = ecma_op_function_get_compiled_code (ext_function_p); + shared_class_fields.header.function_object_p = &ext_function_p->object; + + ecma_object_t *scope_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_function_p->u.function.scope_cp); + + result = vm_run (&shared_class_fields.header, this_val, scope_p); + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED); + return result; +} /* opfunc_init_class_fields */ + +/** + * Initialize static class fields. + * + * @return ECMA_VALUE_ERROR - initialization fails + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +opfunc_init_static_class_fields (ecma_value_t function_object, /**< the function itself */ + ecma_value_t this_val) /**< this_arg of the function */ +{ + JERRY_ASSERT (ecma_op_is_callable (function_object)); + JERRY_ASSERT (ecma_is_value_object (this_val)); + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_object_t *function_object_p = ecma_get_object_from_value (function_object); + ecma_property_t *class_field_property_p = ecma_find_named_property (function_object_p, name_p); + + vm_frame_ctx_shared_class_fields_t shared_class_fields; + shared_class_fields.header.function_object_p = function_object_p; + shared_class_fields.header.status_flags = VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS; + shared_class_fields.computed_class_fields_p = NULL; + + if (class_field_property_p != NULL) + { + ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (class_field_property_p)->value; + shared_class_fields.computed_class_fields_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); + } + + ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) function_object_p; + shared_class_fields.header.bytecode_header_p = ecma_op_function_get_compiled_code (ext_function_p); + + ecma_object_t *scope_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_function_p->u.function.scope_cp); + + ecma_value_t result = vm_run (&shared_class_fields.header, this_val, scope_p); + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED); + return result; +} /* opfunc_init_static_class_fields */ + +/** + * Add the name of a computed field to a name list + * + * @return ECMA_VALUE_ERROR - name is not a valid property name + * ECMA_VALUE_UNDEFINED - otherwise + */ +ecma_value_t +opfunc_add_computed_field (ecma_value_t class_object, /**< class object */ + ecma_value_t name) /**< name of the property */ +{ + ecma_string_t *prop_name_p = ecma_op_to_property_key (name); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + if (ecma_prop_name_is_symbol (prop_name_p)) + { + name = ecma_make_symbol_value (prop_name_p); + } + else + { + name = ecma_make_string_value (prop_name_p); + } + + ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_object_t *class_object_p = ecma_get_object_from_value (class_object); + + ecma_property_t *property_p = ecma_find_named_property (class_object_p, name_p); + ecma_value_t *compact_collection_p; + ecma_property_value_t *property_value_p; + + if (property_p == NULL) + { + ECMA_CREATE_INTERNAL_PROPERTY (class_object_p, name_p, property_p, property_value_p); + compact_collection_p = ecma_new_compact_collection (); + } + else + { + property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, property_value_p->value); + } + + compact_collection_p = ecma_compact_collection_push_back (compact_collection_p, name); + ECMA_SET_INTERNAL_VALUE_POINTER (property_value_p->value, compact_collection_p); + return ECMA_VALUE_UNDEFINED; +} /* opfunc_add_computed_field */ + +/** + * Create implicit class constructor + * + * See also: ECMAScript v6, 14.5.14 + * + * @return - new external function ecma-object + */ +ecma_value_t +opfunc_create_implicit_class_constructor (uint8_t opcode, /**< current cbc opcode */ + const ecma_compiled_code_t *bytecode_p) /**< current byte code */ +{ + /* 8. */ + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (JERRY_UNLIKELY (script_p->refs_and_type >= CBC_SCRIPT_REF_MAX)) + { + jerry_fatal (JERRY_FATAL_REF_COUNT_LIMIT); + } + + ecma_object_t *function_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), + sizeof (ecma_extended_object_t), + ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + + ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) function_object_p; + + script_p->refs_and_type += CBC_SCRIPT_REF_ONE; + constructor_object_p->u.constructor_function.script_value = script_value; + constructor_object_p->u.constructor_function.flags = 0; + + /* 10.a.i */ + if (opcode == CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE) + { + constructor_object_p->u.constructor_function.flags |= ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE; + } + + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (function_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + prop_value_p->value = ecma_make_uint32_value (0); + + return ecma_make_object_value (function_object_p); +} /* opfunc_create_implicit_class_constructor */ + +/** + * Set the [[HomeObject]] attribute of the given functon object + * + * @return void + */ +void +opfunc_set_home_object (ecma_object_t *func_p, /**< function object */ + ecma_object_t *parent_env_p) /**< parent environment */ +{ + JERRY_ASSERT (ecma_is_lexical_environment (parent_env_p)); + + if (ecma_get_object_type (func_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, + parent_env_p, + JMEM_CP_GET_POINTER_TAG_BITS (ext_func_p->u.function.scope_cp)); + } +} /* opfunc_set_home_object */ + +/** + * Make private key from descriptor + * + * @return pointer to private key + */ +ecma_string_t * +opfunc_make_private_key (ecma_value_t descriptor) /**< descriptor */ +{ + ecma_string_t *private_key_p = ecma_new_symbol_from_descriptor_string (descriptor); + private_key_p->u.hash |= ECMA_SYMBOL_FLAG_PRIVATE_KEY; + + return (ecma_string_t *) private_key_p; +} /* opfunc_make_private_key */ + +/** + * Find a private property in the private elements internal property given the key + * + * @return pointer to the private property - if it is found, + * NULL - othervise + */ +static ecma_property_t * +opfunc_find_private_key (ecma_object_t *class_object_p, /**< class environment */ + ecma_object_t *obj_p, /**< object */ + ecma_string_t *search_key_p, /**< key */ + ecma_string_t **out_private_key_p) /**< [out] private key */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + return NULL; + } + + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p == NULL) + { + return NULL; + } + + ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + current_p++; /* skip kind */ + ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++); + current_p++; /* skip value */ + + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + ecma_string_t *private_key_desc_p = + ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor); + + if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p)) + { + prop_p = ecma_find_named_property (obj_p, private_key_p); + + if (out_private_key_p) + { + *out_private_key_p = private_key_p; + } + + return prop_p; + } + } + + return NULL; +} /* opfunc_find_private_key */ + +/** + * PrivateElementFind abstact operation + * + * See also: ECMAScript v12, 7.3.27 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +static ecma_property_t * +opfunc_find_private_element (ecma_object_t *obj_p, /**< object */ + ecma_string_t *key_p, /**< key */ + ecma_string_t **private_key_p, /**< [out] private key */ + bool allow_heritage) /**< heritage flag */ +{ + JERRY_ASSERT (private_key_p != NULL); + JERRY_ASSERT (*private_key_p == NULL); + ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + + while (true) + { + JERRY_ASSERT (lex_env_p != NULL); + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) != 0 + && !ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p)) + { + ecma_object_t *class_object_p = ((ecma_lexical_environment_class_t *) lex_env_p)->object_p; + + ecma_property_t *prop_p = opfunc_find_private_key (class_object_p, obj_p, key_p, private_key_p); + + if (prop_p || *private_key_p != NULL) + { + /* Found non shadowed property */ + return prop_p; + } + + if (!allow_heritage) + { + return NULL; + } + } + + if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL) + { + break; + } + + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + return NULL; +} /* opfunc_find_private_element */ + +/** + * In expression runtime evaluation in case of private identifiers + * + * See also: ECMAScript v12, 13.10.1 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the property was found in the base object + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +opfunc_private_in (ecma_value_t base, /**< base */ + ecma_value_t property) /**< property */ +{ + if (!ecma_is_value_object (base)) + { + return ecma_raise_type_error (ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (base); + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, false); + + return ecma_make_boolean_value (prop_p != NULL); +} /* opfunc_private_in */ + +/** + * PrivateFieldAdd abstact operation + * + * See also: ECMAScript v12, 7.3.28 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_private_field_add (ecma_value_t base, /**< base object */ + ecma_value_t property, /**< property name */ + ecma_value_t value) /**< ecma value */ +{ + ecma_object_t *obj_p = ecma_get_object_from_value (base); + ecma_string_t *prop_name_p = ecma_get_string_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, false); + + if (prop_p != NULL) + { + return ecma_raise_type_error (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE); + } + + ecma_property_value_t *value_p = + ecma_create_named_data_property (obj_p, private_key_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + value_p->value = ecma_copy_value_if_not_object (value); + + return ECMA_VALUE_EMPTY; +} /* opfunc_private_field_add */ + +/** + * PrivateSet abstact operation + * + * See also: ECMAScript v12, 7.3.31 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_private_set (ecma_value_t base, /**< this object */ + ecma_value_t property, /**< property name */ + ecma_value_t value) /**< ecma value */ +{ + ecma_value_t base_obj = ecma_op_to_object (base); + + if (ECMA_IS_VALUE_ERROR (base_obj)) + { + return base_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (base_obj); + ecma_string_t *prop_name_p = ecma_get_string_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, true); + + ecma_value_t result; + + if (prop_p == NULL) + { + result = ecma_raise_type_error (ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT); + } + else if (*prop_p & ECMA_PROPERTY_FLAG_DATA) + { + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + if (private_key_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD) + { + result = ecma_raise_type_error (ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE); + } + else + { + ecma_value_assign_value (&ECMA_PROPERTY_VALUE_PTR (prop_p)->value, value); + result = ecma_copy_value (value); + } + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_p)); + + if (get_set_pair_p->setter_cp == JMEM_CP_NULL) + { + result = ecma_raise_type_error (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER); + } + else + { + ecma_object_t *setter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp); + + result = ecma_op_function_call (setter_p, base, &value, 1); + } + } + + ecma_deref_object (obj_p); + + return result; +} /* opfunc_private_set */ + +/** + * PrivateGet abstact operation + * + * See also: ECMAScript v12, 7.3.30 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * private property value - otherwise + */ +ecma_value_t +opfunc_private_get (ecma_value_t base, /**< this object */ + ecma_value_t property) /**< property name */ +{ + ecma_value_t base_obj = ecma_op_to_object (base); + + if (ECMA_IS_VALUE_ERROR (base_obj)) + { + return base_obj; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (base_obj); + ecma_string_t *prop_name_p = ecma_get_string_from_value (property); + ecma_string_t *private_key_p = NULL; + + ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, true); + + ecma_value_t result; + + if (prop_p == NULL) + { + result = ecma_raise_type_error (ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT); + } + else if (*prop_p & ECMA_PROPERTY_FLAG_DATA) + { + result = ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + } + else + { + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_p)); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + result = ecma_raise_type_error (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER); + } + else + { + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + result = ecma_op_function_call (getter_p, base, NULL, 0); + } + } + + ecma_deref_object (obj_p); + + return result; +} /* opfunc_private_get */ + +/** + * Find the private property in the object who's private key descriptor matches the given key + * + * @return pointer to private key + */ +static ecma_string_t * +opfunc_create_private_key (ecma_value_t *collection_p, /**< collection of private properties */ + ecma_value_t search_key, /**< key */ + ecma_private_property_kind_t search_kind) /**< kind of the property */ +{ + if (search_kind < ECMA_PRIVATE_GETTER) + { + return opfunc_make_private_key (search_key); + } + + ecma_string_t *search_key_p = ecma_get_string_from_value (search_key); + + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + ecma_private_property_kind_t kind = ECMA_PRIVATE_PROPERTY_KIND (*current_p++); + ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++); + current_p++; /* skip value */ + + if (kind < ECMA_PRIVATE_GETTER) + { + continue; + } + + JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p)); + + ecma_string_t *private_key_desc_p = + ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor); + + if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p)) + { + ecma_deref_ecma_string (search_key_p); + ecma_ref_ecma_string (private_key_p); + return private_key_p; + } + } + + return opfunc_make_private_key (search_key); +} /* opfunc_create_private_key */ + +/** + * Collect private members for PrivateMethodOrAccessorAdd and PrivateFieldAdd abstract operations + */ +void +opfunc_collect_private_properties (ecma_value_t constructor, /**< constructor */ + ecma_value_t prop_name, /**< property name */ + ecma_value_t value, /**< value */ + uint8_t opcode) /**< opcode */ +{ + ecma_private_property_kind_t kind = ECMA_PRIVATE_FIELD; + bool is_static = false; + + if (opcode >= CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD) + { + opcode = (uint8_t) (opcode - PARSER_STATIC_PRIVATE_TO_PRIVATE_OFFSET); + is_static = true; + } + + if (opcode == CBC_EXT_COLLECT_PRIVATE_METHOD) + { + prop_name ^= value; + value ^= prop_name; + prop_name ^= value; + kind = ECMA_PRIVATE_METHOD; + } + else if (opcode == CBC_EXT_COLLECT_PRIVATE_GETTER) + { + kind = ECMA_PRIVATE_GETTER; + } + else if (opcode == CBC_EXT_COLLECT_PRIVATE_SETTER) + { + kind = ECMA_PRIVATE_SETTER; + } + + JERRY_ASSERT (ecma_is_value_object (constructor)); + JERRY_ASSERT (ecma_is_value_string (prop_name)); + JERRY_ASSERT (ecma_is_value_object (value) || ecma_is_value_undefined (value)); + + ecma_object_t *constructor_p = ecma_get_object_from_value (constructor); + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (constructor_p, internal_string_p); + ecma_value_t *collection_p; + ecma_property_value_t *prop_value_p; + + if (prop_p == NULL) + { + collection_p = ecma_new_compact_collection (); + ECMA_CREATE_INTERNAL_PROPERTY (constructor_p, internal_string_p, prop_p, prop_value_p); + ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, collection_p); + } + else + { + prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p); + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, prop_value_p->value); + } + + ecma_string_t *key_p = opfunc_create_private_key (collection_p, prop_name, kind); + + if (kind != ECMA_PRIVATE_FIELD) + { + key_p->u.hash |= ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD; + } + + if (is_static) + { + kind = (ecma_private_property_kind_t) ((int) kind | (int) ECMA_PRIVATE_PROPERTY_STATIC_FLAG); + } + + collection_p = ecma_compact_collection_push_back (collection_p, (ecma_value_t) kind); + collection_p = ecma_compact_collection_push_back (collection_p, ecma_make_symbol_value (key_p)); + collection_p = ecma_compact_collection_push_back (collection_p, value); + +#ifndef JERRY_NDEBUG + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + ecma_value_t *current_p = collection_p + 1; + + JERRY_ASSERT ((end_p - current_p) % ECMA_PRIVATE_ELEMENT_LIST_SIZE == 0); +#endif /* !defined (JERRY_NDEBUG) */ + + ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, collection_p); + + ecma_free_value (value); +} /* opfunc_collect_private_properties */ + +/** + * ClassDefinitionEvaluation environment initialization part + * + * See also: ECMAScript v6, 14.5.14 + */ +void +opfunc_push_class_environment (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t **vm_stack_top, /**< VM stack top */ + ecma_value_t class_name) /**< class name */ +{ + JERRY_ASSERT (ecma_is_value_string (class_name)); + ecma_object_t *class_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); + + /* 4.a */ + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (class_env_p, + ecma_get_string_from_value (class_name), + ECMA_PROPERTY_FLAG_ENUMERABLE, + NULL); + + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + frame_ctx_p->lex_env_p = class_env_p; + + *(*vm_stack_top)++ = ECMA_VALUE_RELEASE_LEX_ENV; +} /* opfunc_push_class_environment */ + +/** + * ClassDefinitionEvaluation object initialization part + * + * See also: ECMAScript v6, 14.5.14 + * + * @return - ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_init_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *stack_top_p) /**< stack top */ +{ + /* 5.b, 6.e.ii */ + ecma_object_t *ctor_parent_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + ecma_object_t *proto_parent_p = NULL; + bool free_proto_parent = false; + + ecma_value_t super_class = stack_top_p[-2]; + ecma_object_t *ctor_p = ecma_get_object_from_value (stack_top_p[-1]); + + bool heritage_present = !ecma_is_value_array_hole (super_class); + + /* 5. ClassHeritage opt is not present */ + if (!heritage_present) + { + /* 5.a */ + proto_parent_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + } + else if (!ecma_is_value_null (super_class)) + { + /* 6.f, 6.g.i */ + if (!ecma_is_constructor (super_class)) + { + return ecma_raise_type_error (ECMA_ERR_CLASS_EXTENDS_NOT_CONSTRUCTOR); + } + + ecma_object_t *parent_p = ecma_get_object_from_value (super_class); + + /* 6.g.ii */ + ecma_value_t proto_parent = ecma_op_object_get_by_magic_id (parent_p, LIT_MAGIC_STRING_PROTOTYPE); + + /* 6.g.iii */ + if (ECMA_IS_VALUE_ERROR (proto_parent)) + { + return proto_parent; + } + + /* 6.g.iv */ + if (ecma_is_value_object (proto_parent)) + { + proto_parent_p = ecma_get_object_from_value (proto_parent); + free_proto_parent = true; + } + else if (ecma_is_value_null (proto_parent)) + { + proto_parent_p = NULL; + } + else + { + ecma_free_value (proto_parent); + return ecma_raise_type_error (ECMA_ERR_PROPERTY_PROTOTYPE_IS_NOT_AN_OBJECT); + } + + /* 6.g.v */ + ctor_parent_p = parent_p; + } + + /* 7. */ + ecma_object_t *proto_p = ecma_create_object (proto_parent_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_value_t proto = ecma_make_object_value (proto_p); + + ECMA_SET_POINTER (ctor_p->u2.prototype_cp, ctor_parent_p); + + if (free_proto_parent) + { + ecma_deref_object (proto_parent_p); + } + ecma_free_value (super_class); + + /* 16. */ + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (ctor_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE), + ECMA_PROPERTY_FIXED, + NULL); + property_value_p->value = proto; + + /* 18. */ + property_value_p = ecma_create_named_data_property (proto_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + property_value_p->value = ecma_make_object_value (ctor_p); + + if (ecma_get_object_type (ctor_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + opfunc_bind_class_environment (frame_ctx_p->lex_env_p, proto_p, ctor_p, ctor_p); + + /* 15. set F’s [[ConstructorKind]] internal slot to "derived". */ + if (heritage_present) + { + ECMA_SET_THIRD_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) ctor_p)->u.function.scope_cp); + } + } + + stack_top_p[-2] = stack_top_p[-1]; + stack_top_p[-1] = proto; + + return ECMA_VALUE_EMPTY; +} /* opfunc_init_class */ + +/** + * Creates a new class lexical environment and binds the bound object and the class's object + * + * @return newly created class lexical environment - if func_obj_p is not present + * NULL - otherwise, also the environment is set as the func_obj_p's scope + */ +ecma_object_t * +opfunc_bind_class_environment (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_object_t *home_object_p, /**< bound object */ + ecma_object_t *ctor_p, /**< constructor object */ + ecma_object_t *func_obj_p) /**< function object */ +{ + ecma_object_t *proto_env_p = ecma_create_lex_env_class (lex_env_p, sizeof (ecma_lexical_environment_class_t)); + ECMA_SET_NON_NULL_POINTER (proto_env_p->u1.bound_object_cp, home_object_p); + ((ecma_lexical_environment_class_t *) proto_env_p)->object_p = ctor_p; + ((ecma_lexical_environment_class_t *) proto_env_p)->type = ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV; + + if (func_obj_p) + { + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + ECMA_SET_NON_NULL_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp, proto_env_p, 0); + ecma_deref_object (proto_env_p); + return NULL; + } + + return proto_env_p; +} /* opfunc_bind_class_environment */ + +/** + * Set [[Enumerable]] and [[HomeObject]] attributes for all class method + */ +static void +opfunc_set_class_attributes (ecma_object_t *obj_p, /**< object */ + ecma_object_t *parent_env_p) /**< parent environment */ +{ + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; + + for (uint32_t index = 0; index < ECMA_PROPERTY_PAIR_ITEM_COUNT; index++) + { + uint8_t property = property_pair_p->header.types[index]; + + if (!ECMA_PROPERTY_IS_RAW (property)) + { + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_DELETED + || (ECMA_PROPERTY_IS_INTERNAL (property) + && LIT_INTERNAL_MAGIC_STRING_IGNORED (property_pair_p->names_cp[index]))); + continue; + } + + if (property & ECMA_PROPERTY_FLAG_DATA) + { + if (ecma_is_value_object (property_pair_p->values[index].value) && ecma_is_property_enumerable (property)) + { + property_pair_p->header.types[index] = (uint8_t) (property & ~ECMA_PROPERTY_FLAG_ENUMERABLE); + opfunc_set_home_object (ecma_get_object_from_value (property_pair_p->values[index].value), parent_env_p); + } + continue; + } + + property_pair_p->header.types[index] = (uint8_t) (property & ~ECMA_PROPERTY_FLAG_ENUMERABLE); + ecma_property_value_t *accessor_objs_p = property_pair_p->values + index; + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p); + + if (get_set_pair_p->getter_cp != JMEM_CP_NULL) + { + opfunc_set_home_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp), parent_env_p); + } + + if (get_set_pair_p->setter_cp != JMEM_CP_NULL) + { + opfunc_set_home_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp), parent_env_p); + } + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } +} /* opfunc_set_class_attributes */ + +/** + * Set [[HomeObject]] attributes for all class private elements + */ +static void +opfunc_set_private_instance_method_attributes (ecma_object_t *class_object_p, /**< class constructor */ + ecma_object_t *parent_env_p) /**< parent environment */ +{ + ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS); + ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p); + + if (prop_p == NULL) + { + return; + } + + ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); + ecma_value_t *current_p = collection_p + 1; + ecma_value_t *end_p = ecma_compact_collection_end (collection_p); + + while (current_p < end_p) + { + current_p += 2; /* skip kind, name */ + ecma_value_t value = *current_p++; + + if (!ecma_is_value_undefined (value)) + { + opfunc_set_home_object (ecma_get_object_from_value (value), parent_env_p); + } + } +} /* opfunc_set_private_instance_method_attributes */ + +/** + * Pop the current lexical environment referenced by the frame context + */ +void +opfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + ecma_object_t *outer_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, frame_ctx_p->lex_env_p->u2.outer_reference_cp); + ecma_deref_object (frame_ctx_p->lex_env_p); + frame_ctx_p->lex_env_p = outer_env_p; +} /* opfunc_pop_lexical_environment */ + +/** + * ClassDefinitionEvaluation finalization part + * + * See also: ECMAScript v6, 14.5.14 + */ +void +opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t **vm_stack_top_p, /**< current vm stack top */ + ecma_value_t class_name) /**< class name */ +{ + JERRY_ASSERT (ecma_is_value_undefined (class_name) || ecma_is_value_string (class_name)); + ecma_value_t *stack_top_p = *vm_stack_top_p; + + ecma_object_t *ctor_p = ecma_get_object_from_value (stack_top_p[-2]); + ecma_object_t *proto_p = ecma_get_object_from_value (stack_top_p[-1]); + + ecma_object_t *class_env_p = frame_ctx_p->lex_env_p; + + /* 23.a */ + if (!ecma_is_value_undefined (class_name)) + { + ecma_op_initialize_binding (class_env_p, ecma_get_string_from_value (class_name), stack_top_p[-2]); + } + + ecma_object_t *ctor_env_p = opfunc_bind_class_environment (class_env_p, ctor_p, ctor_p, NULL); + ecma_object_t *proto_env_p = opfunc_bind_class_environment (class_env_p, proto_p, ctor_p, NULL); + + opfunc_set_class_attributes (ctor_p, ctor_env_p); + opfunc_set_class_attributes (proto_p, proto_env_p); + opfunc_set_private_instance_method_attributes (ctor_p, proto_env_p); + + ecma_deref_object (proto_env_p); + ecma_deref_object (ctor_env_p); + ecma_deref_object (proto_p); + + JERRY_ASSERT ((ecma_is_value_undefined (class_name) ? stack_top_p[-3] == ECMA_VALUE_UNDEFINED + : stack_top_p[-3] == ECMA_VALUE_RELEASE_LEX_ENV)); + + /* only the current class remains on the stack */ + if (stack_top_p[-3] == ECMA_VALUE_RELEASE_LEX_ENV) + { + opfunc_pop_lexical_environment (frame_ctx_p); + } + + ecma_value_t result = opfunc_private_method_or_accessor_add (ctor_p, ctor_p, ECMA_PRIVATE_PROPERTY_STATIC_FLAG); + JERRY_ASSERT (ecma_is_value_undefined (result)); + + stack_top_p[-3] = stack_top_p[-2]; + *vm_stack_top_p -= 2; +} /* opfunc_finalize_class */ + +/** + * MakeSuperPropertyReference operation + * + * See also: ECMAScript v6, 12.3.5.3 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stack top */ + vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t prop_name, /**< property name to resolve */ + uint8_t opcode) /**< current cbc opcode */ +{ + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p); + + if (environment_record_p && !ecma_op_this_binding_is_initialized (environment_record_p)) + { + return ecma_raise_reference_error (ECMA_ERR_CALL_SUPER_CONSTRUCTOR_DERIVED_CLASS_BEFORE_THIS); + } + + ecma_value_t parent = ecma_op_resolve_super_base (frame_ctx_p->lex_env_p); + + if (ECMA_IS_VALUE_ERROR (parent)) + { + return ecma_raise_type_error (ECMA_ERR_INVOKE_NULLABLE_SUPER_METHOD); + } + + if (!ecma_op_require_object_coercible (parent)) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t *stack_top_p = *vm_stack_top_p; + + if (opcode >= CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE) + { + JERRY_ASSERT (opcode == CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE + || opcode == CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE); + *stack_top_p++ = parent; + *stack_top_p++ = ecma_copy_value (prop_name); + *vm_stack_top_p = stack_top_p; + + return ECMA_VALUE_EMPTY; + } + + ecma_object_t *parent_p = ecma_get_object_from_value (parent); + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name); + + if (prop_name_p == NULL) + { + ecma_deref_object (parent_p); + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding); + ecma_deref_ecma_string (prop_name_p); + ecma_deref_object (parent_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + if (opcode == CBC_EXT_SUPER_PROP_LITERAL_REFERENCE || opcode == CBC_EXT_SUPER_PROP_REFERENCE) + { + *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding); + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + } + + *stack_top_p++ = result; + *vm_stack_top_p = stack_top_p; + + return ECMA_VALUE_EMPTY; +} /* opfunc_form_super_reference */ + +/** + * Assignment operation for SuperRefence base + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top */ + vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + uint32_t opcode_data) /**< opcode data to store the result */ +{ + ecma_value_t *stack_top_p = *vm_stack_top_p; + + ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]); + + if (ECMA_IS_VALUE_ERROR (base_obj)) + { + return base_obj; + } + + ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj); + ecma_string_t *prop_name_p = ecma_op_to_property_key (stack_top_p[-2]); + + if (prop_name_p == NULL) + { + ecma_deref_object (base_obj_p); + return ECMA_VALUE_ERROR; + } + + bool is_strict = (frame_ctx_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0; + + ecma_value_t result = + ecma_op_object_put_with_receiver (base_obj_p, prop_name_p, stack_top_p[-1], frame_ctx_p->this_binding, is_strict); + + ecma_deref_ecma_string (prop_name_p); + ecma_deref_object (base_obj_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } + + for (int32_t i = 1; i <= 3; i++) + { + ecma_free_value (stack_top_p[-i]); + } + + stack_top_p -= 3; + + if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = result; + } + else if (opcode_data & VM_OC_PUT_BLOCK) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = result; + } + + *vm_stack_top_p = stack_top_p; + + return result; +} /* opfunc_assign_super_reference */ + +/** + * Copy data properties of an object + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */ + ecma_value_t source_object, /**< source object */ + ecma_value_t filter_array) /**< filter array */ +{ + bool source_to_object = false; + + if (!ecma_is_value_object (source_object)) + { + source_object = ecma_op_to_object (source_object); + + if (ECMA_IS_VALUE_ERROR (source_object)) + { + return source_object; + } + + source_to_object = true; + } + + ecma_object_t *source_object_p = ecma_get_object_from_value (source_object); + ecma_collection_t *names_p = ecma_op_object_own_property_keys (source_object_p, JERRY_PROPERTY_FILTER_ALL); + +#if JERRY_BUILTIN_PROXY + if (names_p == NULL) + { + JERRY_ASSERT (!source_to_object); + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_object_t *target_object_p = ecma_get_object_from_value (target_object); + ecma_value_t *buffer_p = names_p->buffer_p; + ecma_value_t *buffer_end_p = buffer_p + names_p->item_count; + ecma_value_t *filter_start_p = NULL; + ecma_value_t *filter_end_p = NULL; + ecma_value_t result = ECMA_VALUE_EMPTY; + + if (filter_array != ECMA_VALUE_UNDEFINED) + { + ecma_object_t *filter_array_p = ecma_get_object_from_value (filter_array); + + JERRY_ASSERT (ecma_get_object_type (filter_array_p) == ECMA_OBJECT_TYPE_ARRAY); + JERRY_ASSERT (ecma_op_object_is_fast_array (filter_array_p)); + + if (filter_array_p->u1.property_list_cp != JMEM_CP_NULL) + { + filter_start_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, filter_array_p->u1.property_list_cp); + filter_end_p = filter_start_p + ((ecma_extended_object_t *) filter_array_p)->u.array.length; + } + } + + while (buffer_p < buffer_end_p) + { + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (*buffer_p++); + + if (filter_start_p != NULL) + { + ecma_value_t *filter_p = filter_start_p; + + do + { + if (ecma_compare_ecma_strings (property_name_p, ecma_get_prop_name_from_value (*filter_p))) + { + break; + } + } while (++filter_p < filter_end_p); + + if (filter_p != filter_end_p) + { + continue; + } + } + + ecma_property_descriptor_t descriptor; + result = ecma_op_object_get_own_property_descriptor (source_object_p, property_name_p, &descriptor); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + + if (result == ECMA_VALUE_FALSE) + { + continue; + } + + if (!(descriptor.flags & JERRY_PROP_IS_ENUMERABLE)) + { + ecma_free_property_descriptor (&descriptor); + continue; + } + + if ((descriptor.flags & JERRY_PROP_IS_VALUE_DEFINED) && !ECMA_OBJECT_IS_PROXY (source_object_p)) + { + result = descriptor.value; + } + else + { + ecma_free_property_descriptor (&descriptor); + + result = ecma_op_object_get (source_object_p, property_name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + break; + } + } + + opfunc_set_data_property (target_object_p, property_name_p, result); + ecma_free_value (result); + + result = ECMA_VALUE_EMPTY; + } + + if (JERRY_UNLIKELY (source_to_object)) + { + ecma_deref_object (source_object_p); + } + + ecma_collection_free (names_p); + return result; +} /* opfunc_copy_data_properties */ + +/** + * Check whether the current lexical scope has restricted binding declaration with the given name + * + * Steps are include ES11: 8.1.1.4.14 HasRestrictedGlobalProperty abstract operation + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if it has restricted property binding + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_string_t *name_p) /**< binding name */ +{ + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + +#if JERRY_BUILTIN_REALMS + JERRY_ASSERT (frame_ctx_p->this_binding == JERRY_CONTEXT (global_object_p)->this_binding); +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_ASSERT (frame_ctx_p->this_binding == ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + ecma_property_t *binding_p = ecma_find_named_property (lex_env_p, name_p); + + if (binding_p != NULL) + { + return ECMA_VALUE_TRUE; + } + +#if JERRY_BUILTIN_REALMS + ecma_object_t *const global_scope_p = ecma_get_global_scope ((ecma_object_t *) JERRY_CONTEXT (global_object_p)); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *const global_scope_p = ecma_get_global_scope (global_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + + if (global_scope_p != lex_env_p) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *global_obj_p = ecma_get_object_from_value (frame_ctx_p->this_binding); + +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (global_obj_p)) + { + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (global_obj_p, name_p, &prop_desc); + + if (ecma_is_value_true (status)) + { + status = ecma_make_boolean_value ((prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE) == 0); + ecma_free_property_descriptor (&prop_desc); + } + + return status; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_t property = ecma_op_object_get_own_property (global_obj_p, name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); + + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || ECMA_PROPERTY_IS_FOUND (property)); + + return ecma_make_boolean_value (property != ECMA_PROPERTY_TYPE_NOT_FOUND + && !ecma_is_property_configurable (property)); +} /* opfunc_lexical_scope_has_restricted_binding */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.h b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.h new file mode 100644 index 00000000..7a964bc3 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/opcodes.h @@ -0,0 +1,173 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OPCODES_H +#define OPCODES_H + +#include "ecma-globals.h" + +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_opcodes Opcodes + * @{ + */ + +/** + * Number arithmetic operations. + */ +typedef enum +{ + NUMBER_ARITHMETIC_SUBTRACTION, /**< subtraction */ + NUMBER_ARITHMETIC_MULTIPLICATION, /**< multiplication */ + NUMBER_ARITHMETIC_DIVISION, /**< division */ + NUMBER_ARITHMETIC_REMAINDER, /**< remainder calculation */ + NUMBER_ARITHMETIC_EXPONENTIATION, /**< exponentiation */ +} number_arithmetic_op; + +/** + * Number bitwise logic operations. + */ +typedef enum +{ + NUMBER_BITWISE_LOGIC_AND, /**< bitwise AND calculation */ + NUMBER_BITWISE_LOGIC_OR, /**< bitwise OR calculation */ + NUMBER_BITWISE_LOGIC_XOR, /**< bitwise XOR calculation */ + NUMBER_BITWISE_SHIFT_LEFT, /**< bitwise LEFT SHIFT calculation */ + NUMBER_BITWISE_SHIFT_RIGHT, /**< bitwise RIGHT_SHIFT calculation */ + NUMBER_BITWISE_SHIFT_URIGHT, /**< bitwise UNSIGNED RIGHT SHIFT calculation */ +} number_bitwise_logic_op; + +/** + * Types for opfunc_create_executable_object. + */ +typedef enum +{ + VM_CREATE_EXECUTABLE_OBJECT_GENERATOR, /**< create a generator function */ + VM_CREATE_EXECUTABLE_OBJECT_ASYNC, /**< create an async function */ +} vm_create_executable_object_type_t; + +/** + * The stack contains spread object during the upcoming APPEND_ARRAY operation + */ +#define OPFUNC_HAS_SPREAD_ELEMENT (1 << 8) + +ecma_value_t opfunc_equality (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t do_number_arithmetic (number_arithmetic_op op, ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_unary_operation (ecma_value_t left_value, bool is_plus); + +ecma_value_t do_number_bitwise_logic (number_bitwise_logic_op op, ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t do_number_bitwise_not (ecma_value_t value); + +ecma_value_t opfunc_addition (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_relation (ecma_value_t left_value, ecma_value_t right_value, bool left_first, bool is_invert); + +ecma_value_t opfunc_in (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_instanceof (ecma_value_t left_value, ecma_value_t right_value); + +ecma_value_t opfunc_typeof (ecma_value_t left_value); + +void opfunc_set_data_property (ecma_object_t *object_p, ecma_string_t *prop_name_p, ecma_value_t value); + +void opfunc_set_accessor (bool is_getter, ecma_value_t object, ecma_string_t *accessor_name_p, ecma_value_t accessor); + +ecma_value_t vm_op_delete_prop (ecma_value_t object, ecma_value_t property, bool is_strict); + +ecma_value_t vm_op_delete_var (ecma_value_t name_literal, ecma_object_t *lex_env_p); + +ecma_collection_t *opfunc_for_in (ecma_value_t left_value, ecma_value_t *result_obj_p); + +ecma_collection_t *opfunc_spread_arguments (ecma_value_t *stack_top_p, uint8_t argument_list_len); + +ecma_value_t opfunc_append_array (ecma_value_t *stack_top_p, uint16_t values_length); + +vm_executable_object_t *opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, + vm_create_executable_object_type_t type); + +extern const uint8_t opfunc_resume_executable_object_with_throw[]; +extern const uint8_t opfunc_resume_executable_object_with_return[]; + +ecma_value_t opfunc_resume_executable_object (vm_executable_object_t *executable_object_p, ecma_value_t value); + +void opfunc_async_generator_yield (ecma_extended_object_t *async_generator_object_p, ecma_value_t value); + +ecma_value_t opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, ecma_value_t value, uint16_t extra_flags); + +ecma_value_t opfunc_init_class_fields (ecma_object_t *class_object_p, ecma_value_t this_val); + +ecma_value_t opfunc_init_static_class_fields (ecma_value_t function_object, ecma_value_t this_val); + +ecma_value_t opfunc_add_computed_field (ecma_value_t class_object, ecma_value_t name); + +ecma_value_t opfunc_create_implicit_class_constructor (uint8_t opcode, const ecma_compiled_code_t *bytecode_p); + +void opfunc_set_home_object (ecma_object_t *func_p, ecma_object_t *parent_env_p); + +ecma_value_t opfunc_define_field (ecma_value_t base, ecma_value_t property, ecma_value_t value); + +ecma_string_t *opfunc_make_private_key (ecma_value_t descriptor); + +ecma_value_t opfunc_private_in (ecma_value_t base, ecma_value_t property); + +ecma_value_t opfunc_private_field_add (ecma_value_t base, ecma_value_t property, ecma_value_t value); + +ecma_value_t opfunc_private_set (ecma_value_t base, ecma_value_t property, ecma_value_t value); + +ecma_value_t opfunc_private_get (ecma_value_t base, ecma_value_t property); + +void opfunc_collect_private_properties (ecma_value_t constructor, + ecma_value_t prop_name, + ecma_value_t method, + uint8_t opcode); + +void opfunc_push_class_environment (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top, ecma_value_t class_name); + +ecma_value_t opfunc_init_class (vm_frame_ctx_t *frame_context_p, ecma_value_t *stack_top_p); + +ecma_object_t *opfunc_bind_class_environment (ecma_object_t *lex_env_p, + ecma_object_t *home_object_p, + ecma_object_t *ctor_p, + ecma_object_t *func_obj_p); + +void opfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p); + +void opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top_p, ecma_value_t class_name); + +ecma_value_t opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, + vm_frame_ctx_t *frame_ctx_p, + ecma_value_t prop_name, + uint8_t opcode); + +ecma_value_t +opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *frame_ctx_p, uint32_t opcode_data); + +ecma_value_t +opfunc_copy_data_properties (ecma_value_t target_object, ecma_value_t source_object, ecma_value_t filter_array); + +ecma_value_t opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *vm_frame_ctx_p, ecma_string_t *name_p); + +/** + * @} + * @} + */ + +#endif /* !OPCODES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-defines.h b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-defines.h new file mode 100644 index 00000000..7ca78131 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-defines.h @@ -0,0 +1,169 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef VM_DEFINES_H +#define VM_DEFINES_H + +#include "ecma-globals.h" + +#include "byte-code.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_executor Executor + * @{ + */ + +/** + * Helper for += on uint16_t values. + */ +#define VM_PLUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) + (value)) + +/** + * Helper for -= on uint16_t values. + */ +#define VM_MINUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) - (value)) + +/** + * Flag bits of vm_frame_ctx_shared_t + */ +typedef enum +{ + VM_FRAME_CTX_SHARED_HAS_ARG_LIST = (1 << 0), /**< has argument list */ + VM_FRAME_CTX_SHARED_DIRECT_EVAL = (1 << 1), /**< direct eval call */ + VM_FRAME_CTX_SHARED_FREE_THIS = (1 << 2), /**< free this binding */ + VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV = (1 << 3), /**< free local environment */ + VM_FRAME_CTX_SHARED_NON_ARROW_FUNC = (1 << 4), /**< non-arrow function */ + VM_FRAME_CTX_SHARED_HERITAGE_PRESENT = (1 << 5), /**< class heritage present */ + VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS = (1 << 6), /**< has class fields */ + VM_FRAME_CTX_SHARED_EXECUTABLE = (1 << 7), /**< frame is an executable object constructed + * with opfunc_create_executable_object */ +} vm_frame_ctx_shared_flags_t; + +/** + * Shared data between the interpreter and the caller + */ +typedef struct +{ + const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */ + ecma_object_t *function_object_p; /**< function obj */ + uint32_t status_flags; /**< combination of vm_frame_ctx_shared_flags_t bits */ +} vm_frame_ctx_shared_t; + +/** + * Shared data extended with arguments + */ +typedef struct +{ + vm_frame_ctx_shared_t header; /**< shared data header */ + const ecma_value_t *arg_list_p; /**< arguments list */ + uint32_t arg_list_len; /**< arguments list length */ +} vm_frame_ctx_shared_args_t; + +/** + * Shared data extended with computed class fields + */ +typedef struct +{ + vm_frame_ctx_shared_t header; /**< shared data header */ + ecma_value_t *computed_class_fields_p; /**< names of the computed class fields */ +} vm_frame_ctx_shared_class_fields_t; + +/** + * Get the computed class field + */ +#define VM_GET_COMPUTED_CLASS_FIELDS(frame_ctx_p) \ + (((vm_frame_ctx_shared_class_fields_t *) ((frame_ctx_p)->shared_p))->computed_class_fields_p) + +/** + * Flag bits of vm_frame_ctx_t + */ +typedef enum +{ + VM_FRAME_CTX_DIRECT_EVAL = (1 << 1), /**< direct eval call */ + VM_FRAME_CTX_IS_STRICT = (1 << 2), /**< strict mode */ +} vm_frame_ctx_flags_t; + +/** + * Context of interpreter, related to a JS stack frame + */ +typedef struct vm_frame_ctx_t +{ + vm_frame_ctx_shared_t *shared_p; /**< shared information */ + const uint8_t *byte_code_p; /**< current byte code pointer */ + const uint8_t *byte_code_start_p; /**< byte code start pointer */ + ecma_value_t *stack_top_p; /**< stack top pointer */ + ecma_value_t *literal_start_p; /**< literal list start pointer */ + ecma_object_t *lex_env_p; /**< current lexical environment */ + struct vm_frame_ctx_t *prev_context_p; /**< previous context */ + ecma_value_t this_binding; /**< this binding */ + uint16_t context_depth; /**< current context depth */ + uint8_t status_flags; /**< combination of vm_frame_ctx_flags_t bits */ + uint8_t call_operation; /**< perform a call or construct operation */ + /* Registers start immediately after the frame context. */ +} vm_frame_ctx_t; + +/** + * Get register list corresponding to the frame context. + */ +#define VM_GET_REGISTERS(frame_ctx_p) ((ecma_value_t *) ((frame_ctx_p) + 1)) + +/** + * Read or write a specific register. + */ +#define VM_GET_REGISTER(frame_ctx_p, i) (((ecma_value_t *) ((frame_ctx_p) + 1))[i]) + +/** + * Calculate the executable object from a vm_executable_object frame context. + */ +#define VM_GET_EXECUTABLE_OBJECT(frame_ctx_p) \ + ((ecma_extended_object_t *) ((uintptr_t) (frame_ctx_p) - (uintptr_t) offsetof (vm_executable_object_t, frame_ctx))) + +/** + * Calculate the shared_part from a vm_executable_object frame context. + */ +#define VM_GET_EXECUTABLE_ITERATOR(frame_ctx_p) \ + ((ecma_value_t *) ((uintptr_t) (frame_ctx_p) - (uintptr_t) offsetof (vm_executable_object_t, frame_ctx) \ + + (uintptr_t) offsetof (vm_executable_object_t, iterator))) + +/** + * Generator frame context. + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + vm_frame_ctx_shared_t shared; /**< shared part */ + ecma_value_t iterator; /**< executable object's iterator */ + vm_frame_ctx_t frame_ctx; /**< frame context part */ +} vm_executable_object_t; + +/** + * Real backtrace frame data passed to the jerry_backtrace_cb_t handler. + */ +struct jerry_frame_internal_t +{ + vm_frame_ctx_t *context_p; /**< context pointer */ + uint8_t frame_type; /**< frame type */ + jerry_frame_location_t location; /**< location information */ + ecma_value_t function; /**< function reference */ + ecma_value_t this_binding; /**< this binding passed to the function */ +}; + +/** + * @} + * @} + */ + +#endif /* !VM_DEFINES_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.cpp new file mode 100644 index 00000000..62f46c7a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.cpp @@ -0,0 +1,546 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vm-stack.h" + +#include "ecma-alloc.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" + +#include "jcontext.h" +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup stack VM stack + * @{ + */ + +JERRY_STATIC_ASSERT (((int)PARSER_WITH_CONTEXT_STACK_ALLOCATION == (int)PARSER_BLOCK_CONTEXT_STACK_ALLOCATION), + with_context_stack_allocation_must_be_equal_to_block_context_stack_allocation); + +JERRY_STATIC_ASSERT (((int)PARSER_WITH_CONTEXT_STACK_ALLOCATION == (int)PARSER_TRY_CONTEXT_STACK_ALLOCATION), + with_context_stack_allocation_must_be_equal_to_block_context_stack_allocation); + +JERRY_STATIC_ASSERT (((int)PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION == (int)PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION), + for_of_context_stack_allocation_must_be_equal_to_for_await_of_context_stack_allocation); + +/** + * Abort (finalize) the current variable length stack context, and remove it. + * + * @return new stack top + */ +ecma_value_t * +vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *vm_stack_top_p, /**< current stack top */ + uint32_t context_stack_allocation) /**< 0 - if all context element + * should be released + * context stack allocation - otherwise */ +{ + JERRY_ASSERT (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]))); + + uint32_t context_size = VM_GET_CONTEXT_END (vm_stack_top_p[-1]); + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size); + + JERRY_ASSERT (context_size > 0); + --vm_stack_top_p; + + if (context_stack_allocation == 0) + { + context_stack_allocation = context_size; + } + + for (uint32_t i = 1; i < context_stack_allocation; i++) + { + ecma_free_value (*(--vm_stack_top_p)); + } + + return vm_stack_top_p; +} /* vm_stack_context_abort_variable_length */ + +/** + * Abort (finalize) the current stack context, and remove it. + * + * @return new stack top + */ +ecma_value_t * +vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *vm_stack_top_p) /**< current stack top */ +{ + ecma_value_t context_info = vm_stack_top_p[-1]; + + if (context_info & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + switch (VM_GET_CONTEXT_TYPE (context_info)) + { + case VM_CONTEXT_FINALLY_THROW: + case VM_CONTEXT_FINALLY_RETURN: + { + ecma_free_value (vm_stack_top_p[-2]); + /* FALLTHRU */ + } + case VM_CONTEXT_FINALLY_JUMP: + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + break; + } + case VM_CONTEXT_TRY: + case VM_CONTEXT_CATCH: + case VM_CONTEXT_BLOCK: + case VM_CONTEXT_WITH: + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_WITH_CONTEXT_STACK_ALLOCATION; + break; + } + case VM_CONTEXT_ITERATOR: + case VM_CONTEXT_OBJ_INIT: + case VM_CONTEXT_OBJ_INIT_REST: + { + vm_stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, vm_stack_top_p, 0); + break; + } + case VM_CONTEXT_FOR_OF: + case VM_CONTEXT_FOR_AWAIT_OF: + { + ecma_free_value (vm_stack_top_p[-2]); + ecma_free_value (vm_stack_top_p[-3]); + ecma_free_value (vm_stack_top_p[-4]); + + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION; + break; + } + default: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]) == VM_CONTEXT_FOR_IN); + + ecma_collection_t *collection_p; + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, vm_stack_top_p[-2]); + + ecma_value_t *buffer_p = collection_p->buffer_p; + + for (uint32_t index = vm_stack_top_p[-3]; index < collection_p->item_count; index++) + { + ecma_free_value (buffer_p[index]); + } + + ecma_collection_destroy (collection_p); + + ecma_free_value (vm_stack_top_p[-4]); + + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION); + vm_stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + break; + } + } + + return vm_stack_top_p; +} /* vm_stack_context_abort */ + +/** + * Decode branch offset. + * + * @return branch offset + */ +static uint32_t +vm_decode_branch_offset (const uint8_t *branch_offset_p, /**< start offset of byte code */ + uint32_t length) /**< length of the branch */ +{ + uint32_t branch_offset = *branch_offset_p; + + JERRY_ASSERT (length >= 1 && length <= 3); + + switch (length) + { + case 3: + { + branch_offset <<= 8; + branch_offset |= *(++branch_offset_p); + /* FALLTHRU */ + } + case 2: + { + branch_offset <<= 8; + branch_offset |= *(++branch_offset_p); + break; + } + } + + return branch_offset; +} /* vm_decode_branch_offset */ + +/** + * Byte code which resumes an executable object with throw + */ +static const uint8_t vm_stack_resume_executable_object_with_context_end[1] = { CBC_CONTEXT_END }; + +/** + * Find a finally up to the end position. + * + * @return value specified in vm_stack_found_type + */ +vm_stack_found_type +vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t *stack_top_p, /**< current stack top */ + vm_stack_context_type_t finally_type, /**< searching this finally */ + uint32_t search_limit) /**< search up-to this byte code */ +{ + JERRY_ASSERT (finally_type <= VM_CONTEXT_FINALLY_RETURN); + + if (finally_type != VM_CONTEXT_FINALLY_JUMP) + { + search_limit = 0xffffffffu; + } + + while (frame_ctx_p->context_depth > 0) + { + vm_stack_context_type_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]); + uint32_t context_end = VM_GET_CONTEXT_END (stack_top_p[-1]); + JERRY_ASSERT (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) || finally_type != VM_CONTEXT_FINALLY_JUMP); + + if (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) && search_limit < context_end) + { + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_EXPECTED; + } + + if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH) + { + const uint8_t *byte_code_p; + uint32_t branch_offset_length; + uint32_t branch_offset; + + if (search_limit == context_end) + { + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_EXPECTED; + } + + if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + byte_code_p = frame_ctx_p->byte_code_start_p + context_end; + + if (context_type == VM_CONTEXT_TRY) + { + JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE); + + if (byte_code_p[1] >= CBC_EXT_CATCH && byte_code_p[1] <= CBC_EXT_CATCH_3) + { + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]); + branch_offset = vm_decode_branch_offset (byte_code_p + 2, branch_offset_length); + + if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p); + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_CATCH, branch_offset); + + byte_code_p += 2 + branch_offset_length; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_FINALLY; + } + + byte_code_p += branch_offset; + + if (*byte_code_p == CBC_CONTEXT_END) + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION; + continue; + } + } + } + else + { + JERRY_ASSERT (context_type == VM_CONTEXT_CATCH); + + if (byte_code_p[0] == CBC_CONTEXT_END) + { + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION; + continue; + } + } + + JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION); + stack_top_p += PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION; + + if (JERRY_UNLIKELY (byte_code_p[1] == CBC_EXT_ASYNC_EXIT)) + { + branch_offset = (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p); + stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, branch_offset); + + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_FINALLY; + } + + JERRY_ASSERT (byte_code_p[1] >= CBC_EXT_FINALLY && byte_code_p[1] <= CBC_EXT_FINALLY_3); + + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]); + branch_offset = vm_decode_branch_offset (byte_code_p + 2, branch_offset_length); + + branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p); + + stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, branch_offset); + + byte_code_p += 2 + branch_offset_length; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_FINALLY; + } + else if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR) + { + JERRY_ASSERT (context_type == VM_CONTEXT_FOR_OF || context_type == VM_CONTEXT_FOR_AWAIT_OF + || context_type == VM_CONTEXT_ITERATOR); + JERRY_ASSERT (finally_type == VM_CONTEXT_FINALLY_THROW || !jcontext_has_pending_exception ()); + + ecma_value_t exception = ECMA_VALUE_UNDEFINED; + if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + exception = jcontext_take_exception (); + } + + ecma_value_t result; + + if (context_type == VM_CONTEXT_ITERATOR) + { + result = ecma_op_iterator_close (stack_top_p[-2]); + } + else + { + ecma_value_t iterator = stack_top_p[-3]; + result = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN); + + if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_undefined (result)) + { + ecma_object_t *return_obj_p = ecma_get_object_from_value (result); + result = ecma_op_function_validated_call (result, iterator, NULL, 0); + ecma_deref_object (return_obj_p); + + if (context_type == VM_CONTEXT_FOR_AWAIT_OF && !ECMA_IS_VALUE_ERROR (result)) + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + result = ecma_promise_async_await (async_generator_object_p, result); + + if (!ECMA_IS_VALUE_ERROR (result)) + { + uint16_t extra_flags = + (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD | (ECMA_AWAIT_FOR_CLOSE << ECMA_AWAIT_STATE_SHIFT)); + async_generator_object_p->u.cls.u2.executable_obj_flags |= extra_flags; + + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, context_end); + if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + stack_top_p[-2] = exception; + } + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = vm_stack_resume_executable_object_with_context_end; + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_AWAIT; + } + } + + if (!ECMA_IS_VALUE_ERROR (result)) + { + bool is_object = ecma_is_value_object (result); + + ecma_free_value (result); + result = ECMA_VALUE_UNDEFINED; + + if (!is_object) + { + result = ecma_raise_type_error (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT); + } + } + } + } + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (result)) + { + if (finally_type != VM_CONTEXT_FINALLY_THROW) + { + frame_ctx_p->stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + return VM_CONTEXT_FOUND_ERROR; + } + + ecma_free_value (jcontext_take_exception ()); + jcontext_raise_exception (exception); + } + else if (finally_type == VM_CONTEXT_FINALLY_THROW) + { + jcontext_raise_exception (exception); + } + } + + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + } + + frame_ctx_p->stack_top_p = stack_top_p; + return VM_CONTEXT_FOUND_EXPECTED; +} /* vm_stack_find_finally */ + +/** + * Get the offsets of ecma values corresponding to the passed context. + * + * @return array of offsets, last item represents the size of the context item + */ +uint32_t +vm_get_context_value_offsets (ecma_value_t *context_item_p) /**< any item of a context */ +{ + switch (VM_GET_CONTEXT_TYPE (context_item_p[-1])) + { + case VM_CONTEXT_FINALLY_THROW: + case VM_CONTEXT_FINALLY_RETURN: + { + return (PARSER_FINALLY_CONTEXT_STACK_ALLOCATION << VM_CONTEXT_OFFSET_SHIFT) | 2; + } + case VM_CONTEXT_FINALLY_JUMP: + { + return PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + } + case VM_CONTEXT_TRY: + case VM_CONTEXT_CATCH: + case VM_CONTEXT_BLOCK: + case VM_CONTEXT_WITH: + { + return PARSER_WITH_CONTEXT_STACK_ALLOCATION; + } + case VM_CONTEXT_FOR_IN: + { + return (PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION << VM_CONTEXT_OFFSET_SHIFT) | 4; + } + default: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_item_p[-1]) == VM_CONTEXT_FOR_OF + || VM_GET_CONTEXT_TYPE (context_item_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + + return ((PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION << (VM_CONTEXT_OFFSET_SHIFT * 3)) + | (4 << (VM_CONTEXT_OFFSET_SHIFT * 2)) | (3 << VM_CONTEXT_OFFSET_SHIFT) | 2); + } + } +} /* vm_get_context_value_offsets */ + +/** + * Ref / deref lexical environments in the chain using the current context. + */ +void +vm_ref_lex_env_chain (ecma_object_t *lex_env_p, /**< top of lexical environment */ + uint16_t context_depth, /**< depth of function context */ + ecma_value_t *context_end_p, /**< end of function context */ + bool do_ref) /**< ref or deref lexical environments */ +{ + ecma_value_t *context_top_p = context_end_p + context_depth; + JERRY_ASSERT (context_top_p > context_end_p); + + do + { + if (context_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + ecma_object_t *next_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + + if (do_ref) + { + ecma_ref_object (lex_env_p); + } + else + { + ecma_deref_object (lex_env_p); + } + + lex_env_p = next_lex_env_p; + } + + if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1]))) + { + ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]); + JERRY_ASSERT (last_item_p >= context_end_p); + context_top_p--; + + do + { + if (do_ref) + { + ecma_ref_if_object (*(--context_top_p)); + } + else + { + ecma_deref_if_object (*(--context_top_p)); + } + } while (context_top_p > last_item_p); + + continue; + } + + uint32_t offsets = vm_get_context_value_offsets (context_top_p); + + while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) + { + int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets); + + if (do_ref) + { + ecma_ref_if_object (context_top_p[offset]); + } + else + { + ecma_deref_if_object (context_top_p[offset]); + } + + offsets >>= VM_CONTEXT_OFFSET_SHIFT; + } + + JERRY_ASSERT (context_top_p >= context_end_p + offsets); + context_top_p -= offsets; + } while (context_top_p > context_end_p); +} /* vm_ref_lex_env_chain */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.h b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.h new file mode 100644 index 00000000..37fd815a --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-stack.h @@ -0,0 +1,140 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VM_STACK_H +#define VM_STACK_H + +#include "ecma-globals.h" + +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup stack VM stack + * @{ + */ + +/** + * Create context on the vm stack. + */ +#define VM_CREATE_CONTEXT(type, end_offset) ((ecma_value_t) ((type) | ((end_offset) << 7))) + +/** + * Create context on the vm stack with environment. + */ +#define VM_CREATE_CONTEXT_WITH_ENV(type, end_offset) (VM_CREATE_CONTEXT ((type), (end_offset)) | VM_CONTEXT_HAS_LEX_ENV) + +/** + * Get type of a vm context. + */ +#define VM_GET_CONTEXT_TYPE(value) ((vm_stack_context_type_t) ((value) &0x1f)) + +/** + * Get the end position of a vm context. + */ +#define VM_GET_CONTEXT_END(value) ((value) >> 7) + +/** + * This flag is set if the context has a lexical environment. + */ +#define VM_CONTEXT_HAS_LEX_ENV 0x20 + +/** + * This flag is set if the iterator close operation should be invoked during a for-of context break. + */ +#define VM_CONTEXT_CLOSE_ITERATOR 0x40 + +/** + * Context types for the vm stack. + */ +typedef enum +{ + /* Update VM_CONTEXT_IS_FINALLY macro if the following three values are changed. */ + VM_CONTEXT_FINALLY_JUMP, /**< finally context with a jump */ + VM_CONTEXT_FINALLY_THROW, /**< finally context with a throw */ + VM_CONTEXT_FINALLY_RETURN, /**< finally context with a return */ + VM_CONTEXT_TRY, /**< try context */ + VM_CONTEXT_CATCH, /**< catch context */ + VM_CONTEXT_BLOCK, /**< block context */ + VM_CONTEXT_WITH, /**< with context */ + VM_CONTEXT_FOR_IN, /**< for-in context */ + VM_CONTEXT_FOR_OF, /**< for-of context */ + VM_CONTEXT_FOR_AWAIT_OF, /**< for-await-of context */ + + /* contexts with variable length */ + VM_CONTEXT_ITERATOR, /**< iterator context */ + VM_CONTEXT_OBJ_INIT, /**< object-initializer context */ + VM_CONTEXT_OBJ_INIT_REST, /**< object-initializer-rest context */ +} vm_stack_context_type_t; + +/** + * Return types for vm_stack_find_finally. + */ +typedef enum +{ + VM_CONTEXT_FOUND_FINALLY, /**< found finally */ + VM_CONTEXT_FOUND_ERROR, /**< found an error */ + VM_CONTEXT_FOUND_AWAIT, /**< found an await operation */ + VM_CONTEXT_FOUND_EXPECTED, /**< found the type specified in finally_type */ +} vm_stack_found_type; + +/** + * Checks whether the context has variable context size + * + * Layout: + * - [context descriptor] + * - [JS values belong to the context] + * - [previous JS values stored by the VM stack] + */ +#define VM_CONTEXT_IS_VARIABLE_LENGTH(context_type) ((context_type) >= VM_CONTEXT_ITERATOR) + +/** + * Checks whether the context type is a finally type. + */ +#define VM_CONTEXT_IS_FINALLY(context_type) ((context_type) <= VM_CONTEXT_FINALLY_RETURN) + +/** + * Shift needs to be applied to get the next item of the offset array. + */ +#define VM_CONTEXT_OFFSET_SHIFT 4 + +/** + * Checks whether an offset is available. + */ +#define VM_CONTEXT_HAS_NEXT_OFFSET(offsets) ((offsets) >= (1 << VM_CONTEXT_OFFSET_SHIFT)) + +/** + * Get the next offset from the offset array. + */ +#define VM_CONTEXT_GET_NEXT_OFFSET(offsets) (-((int32_t) ((offsets) & ((1 << VM_CONTEXT_OFFSET_SHIFT) - 1)))) + +ecma_value_t *vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, + ecma_value_t *vm_stack_top_p, + uint32_t context_stack_allocation); +ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p); +vm_stack_found_type vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, + ecma_value_t *stack_top_p, + vm_stack_context_type_t finally_type, + uint32_t search_limit); +uint32_t vm_get_context_value_offsets (ecma_value_t *context_item_p); +void vm_ref_lex_env_chain (ecma_object_t *lex_env_p, uint16_t context_depth, ecma_value_t *context_end_p, bool do_ref); + +/** + * @} + * @} + */ + +#endif /* !VM_STACK_H */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm-utils.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-utils.cpp new file mode 100644 index 00000000..ee5b8069 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm-utils.cpp @@ -0,0 +1,136 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-array-object.h" +#include "ecma-helpers.h" +#include "ecma-line-info.h" + +#include "jcontext.h" +#include "lit-char-helpers.h" +#include "vm.h" + +/** + * Check whether currently executed code is strict mode code + * + * @return true - current code is executed in strict mode, + * false - otherwise + */ +bool +vm_is_strict_mode (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (vm_top_context_p) != NULL); + + return JERRY_CONTEXT (vm_top_context_p)->status_flags & VM_FRAME_CTX_IS_STRICT; +} /* vm_is_strict_mode */ + +/** + * Check whether currently performed call (on top of call-stack) is performed in form, + * meeting conditions of 'Direct Call to Eval' (see also: ECMA-262 v5, 15.1.2.1.1) + * + * Warning: + * the function should only be called from implementation + * of built-in 'eval' routine of Global object + * + * @return true - currently performed call is performed through 'eval' identifier, + * without 'this' argument, + * false - otherwise + */ +bool +vm_is_direct_eval_form_call (void) +{ + return (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL) != 0; +} /* vm_is_direct_eval_form_call */ + +/** + * Get backtrace. The backtrace is an array of strings where + * each string contains the position of the corresponding frame. + * The array length is zero if the backtrace is not available. + * + * @return array ecma value + */ +ecma_value_t +vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimited */ +{ +#if JERRY_LINE_INFO + vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); + + if (max_depth == 0) + { + max_depth = UINT32_MAX; + } + + ecma_object_t *array_p = ecma_op_new_array_object (0); + JERRY_ASSERT (ecma_op_object_is_fast_array (array_p)); + uint32_t index = 0; + + while (context_p != NULL) + { + const ecma_compiled_code_t *bytecode_header_p = context_p->shared_p->bytecode_header_p; + ecma_value_t source_name = ecma_get_source_name (bytecode_header_p); + ecma_string_t *str_p = ecma_get_string_from_value (source_name); + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + if (ecma_string_is_empty (str_p)) + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) ":", 10); + } + else + { + ecma_stringbuilder_append (&builder, str_p); + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COLON); + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO) + { + jerry_frame_location_t location; + ecma_line_info_get (ecma_compiled_code_get_line_info (bytecode_header_p), + (uint32_t) (context_p->byte_code_p - context_p->byte_code_start_p), + &location); + + ecma_string_t *line_str_p = ecma_new_ecma_string_from_uint32 (location.line); + ecma_stringbuilder_append (&builder, line_str_p); + ecma_deref_ecma_string (line_str_p); + + ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COLON); + + line_str_p = ecma_new_ecma_string_from_uint32 (location.column); + ecma_stringbuilder_append (&builder, line_str_p); + ecma_deref_ecma_string (line_str_p); + } + else + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "1:1", 3); + } + + ecma_string_t *builder_str_p = ecma_stringbuilder_finalize (&builder); + ecma_fast_array_set_property (array_p, index, ecma_make_string_value (builder_str_p)); + ecma_deref_ecma_string (builder_str_p); + + context_p = context_p->prev_context_p; + index++; + + if (index >= max_depth) + { + break; + } + } + + return ecma_make_object_value (array_p); +#else /* !JERRY_LINE_INFO */ + JERRY_UNUSED (max_depth); + + return ecma_make_object_value (ecma_op_new_array_object (0)); +#endif /* JERRY_LINE_INFO */ +} /* vm_get_backtrace */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm.cpp b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.cpp new file mode 100644 index 00000000..1fbdd36c --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.cpp @@ -0,0 +1,5156 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vm.h" + +#include "ecma-alloc.h" +#include "ecma-arguments-object.h" +#include "ecma-array-object.h" +#include "ecma-bigint.h" +#include "ecma-builtin-object.h" +#include "ecma-builtins.h" +#include "ecma-comparison.h" +#include "ecma-conversion.h" +#include "ecma-errors.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-iterator-object.h" +#include "ecma-lcache.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-regexp-object.h" + +#include "common.h" +#include "jcontext.h" +#include "opcodes.h" +#include "vm-stack.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_executor Executor + * @{ + */ + +JERRY_STATIC_ASSERT ((sizeof (vm_frame_ctx_t) % sizeof (ecma_value_t)) == 0, + sizeof_vm_frame_ctx_must_be_sizeof_ecma_value_t_aligned); + +/** + * Get the value of object[property]. + * + * @return ecma value + */ +static ecma_value_t +vm_op_get_value (ecma_value_t object, /**< base object */ + ecma_value_t property) /**< property name */ +{ + if (ecma_is_value_object (object)) + { + ecma_object_t *object_p = ecma_get_object_from_value (object); + ecma_string_t *property_name_p = NULL; + + if (ecma_is_value_integer_number (property)) + { + ecma_integer_value_t int_value = ecma_get_integer_from_value (property); + + if (int_value >= 0 && int_value <= ECMA_DIRECT_STRING_MAX_IMM) + { + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p) + && (uint32_t) int_value < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + if (JERRY_LIKELY (!ecma_is_value_array_hole (values_p[int_value]))) + { + return ecma_fast_copy_value (values_p[int_value]); + } + } + } + + property_name_p = (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) int_value); + } + } + else if (ecma_is_value_string (property)) + { + property_name_p = ecma_get_string_from_value (property); + } + + if (ecma_is_value_symbol (property)) + { + property_name_p = ecma_get_symbol_from_value (property); + } + + if (property_name_p != NULL) + { +#if JERRY_LCACHE + ecma_property_t *property_p = ecma_lcache_lookup (object_p, property_name_p); + + if (property_p != NULL && (*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + JERRY_ASSERT (!ECMA_PROPERTY_IS_INTERNAL (*property_p)); + return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + } +#endif /* JERRY_LCACHE */ + + /* There is no need to free the name. */ + return ecma_op_object_get (object_p, property_name_p); + } + } + + if (JERRY_UNLIKELY (ecma_is_value_undefined (object) || ecma_is_value_null (object))) + { +#if JERRY_ERROR_MESSAGES + ecma_value_t error_value = + ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, "Cannot read property '%' of %", property, object); +#else /* !JERRY_ERROR_MESSAGES */ + ecma_value_t error_value = ecma_raise_type_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + return error_value; + } + + ecma_string_t *property_name_p = ecma_op_to_property_key (property); + + if (property_name_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t get_value_result = ecma_op_get_value_object_base (object, property_name_p); + + ecma_deref_ecma_string (property_name_p); + return get_value_result; +} /* vm_op_get_value */ + +/** + * Set the value of object[property]. + * + * Note: + * this function frees its object and property arguments + * + * @return an ecma value which contains an error + * if the property setting is unsuccessful + */ +static ecma_value_t +vm_op_set_value (ecma_value_t base, /**< base object */ + ecma_value_t property, /**< property name */ + ecma_value_t value, /**< ecma value */ + bool is_strict) /**< strict mode */ +{ + ecma_value_t result = ECMA_VALUE_EMPTY; + ecma_object_t *object_p; + ecma_string_t *property_p; + + if (JERRY_UNLIKELY (!ecma_is_value_object (base))) + { + if (JERRY_UNLIKELY (ecma_is_value_null (base) || ecma_is_value_undefined (base))) + { +#if JERRY_ERROR_MESSAGES + result = ecma_raise_standard_error_with_format (JERRY_ERROR_TYPE, "Cannot set property '%' of %", property, base); +#else /* !JERRY_ERROR_MESSAGES */ + result = ecma_raise_type_error (ECMA_ERR_EMPTY); +#endif /* JERRY_ERROR_MESSAGES */ + ecma_free_value (property); + return result; + } + + if (JERRY_UNLIKELY (!ecma_is_value_prop_name (property))) + { + property_p = ecma_op_to_string (property); + ecma_fast_free_value (property); + + if (JERRY_UNLIKELY (property_p == NULL)) + { + ecma_free_value (base); + return ECMA_VALUE_ERROR; + } + } + else + { + property_p = ecma_get_prop_name_from_value (property); + } + + ecma_value_t object = ecma_op_to_object (base); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (object)); + + object_p = ecma_get_object_from_value (object); + ecma_op_ordinary_object_prevent_extensions (object_p); + + result = ecma_op_object_put_with_receiver (object_p, property_p, value, base, is_strict); + + ecma_free_value (base); + } + else + { + object_p = ecma_get_object_from_value (base); + + if (JERRY_UNLIKELY (!ecma_is_value_prop_name (property))) + { + property_p = ecma_op_to_string (property); + ecma_fast_free_value (property); + + if (JERRY_UNLIKELY (property_p == NULL)) + { + ecma_deref_object (object_p); + return ECMA_VALUE_ERROR; + } + } + else + { + property_p = ecma_get_prop_name_from_value (property); + } + + if (!ecma_is_lexical_environment (object_p)) + { + result = ecma_op_object_put_with_receiver (object_p, property_p, value, base, is_strict); + } + else + { + result = ecma_op_set_mutable_binding (object_p, property_p, value, is_strict); + } + } + + ecma_deref_object (object_p); + ecma_deref_ecma_string (property_p); + return result; +} /* vm_op_set_value */ + +/** Compact bytecode define */ +#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg4, + +/** + * Decode table for both opcodes and extended opcodes. + */ +static const uint16_t vm_decode_table[] JERRY_ATTR_CONST_DATA = { CBC_OPCODE_LIST CBC_EXT_OPCODE_LIST }; + +#undef CBC_OPCODE + +/** + * Run global code + * + * Note: + * returned value must be freed with ecma_free_value, when it is no longer needed. + * + * @return ecma value + */ +ecma_value_t +vm_run_global (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode to run */ + ecma_object_t *function_object_p) /**< function object if available */ +{ +#if JERRY_BUILTIN_REALMS + ecma_object_t *global_obj_p = (ecma_object_t *) ecma_op_function_get_realm (bytecode_p); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *global_obj_p = ecma_builtin_get_global (); +#endif /* JERRY_BUILTIN_REALMS */ + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED) + { + ecma_create_global_lexical_block (global_obj_p); + } + + ecma_object_t *const global_scope_p = ecma_get_global_scope (global_obj_p); + + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = bytecode_p; + shared.function_object_p = function_object_p; + shared.status_flags = 0; + +#if JERRY_BUILTIN_REALMS + ecma_value_t this_binding = ((ecma_global_object_t *) global_obj_p)->this_binding; + + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) global_obj_p; +#else /* !JERRY_BUILTIN_REALMS */ + ecma_value_t this_binding = ecma_make_object_value (global_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_value_t result = vm_run (&shared, this_binding, global_scope_p); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + return result; +} /* vm_run_global */ + +/** + * Run specified eval-mode bytecode + * + * @return ecma value + */ +ecma_value_t +vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */ + uint32_t parse_opts) /**< ecma_parse_opts_t option bits */ +{ + ecma_value_t this_binding; + ecma_object_t *lex_env_p; + + /* ECMA-262 v5, 10.4.2 */ + if (parse_opts & ECMA_PARSE_DIRECT_EVAL) + { + this_binding = ecma_copy_value (JERRY_CONTEXT (vm_top_context_p)->this_binding); + lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; + } + else + { +#if JERRY_BUILTIN_REALMS + ecma_object_t *global_obj_p = (ecma_object_t *) ecma_op_function_get_realm (bytecode_data_p); + this_binding = ((ecma_global_object_t *) global_obj_p)->this_binding; + ecma_ref_object (ecma_get_object_from_value (this_binding)); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *global_obj_p = ecma_builtin_get_global (); + ecma_ref_object (global_obj_p); + this_binding = ecma_make_object_value (global_obj_p); +#endif /* JERRY_BUILTIN_REALMS */ + lex_env_p = ecma_get_global_scope (global_obj_p); + } + + ecma_ref_object (lex_env_p); + + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0) + { + ecma_object_t *strict_lex_env_p = ecma_create_decl_lex_env (lex_env_p); + + ecma_deref_object (lex_env_p); + lex_env_p = strict_lex_env_p; + } + + if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED) != 0) + { + ecma_object_t *lex_block_p = ecma_create_decl_lex_env (lex_env_p); + lex_block_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + + ecma_deref_object (lex_env_p); + lex_env_p = lex_block_p; + } + + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = bytecode_data_p; + shared.function_object_p = NULL; + shared.status_flags = (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_FRAME_CTX_SHARED_DIRECT_EVAL : 0; + + ecma_value_t completion_value = vm_run (&shared, this_binding, lex_env_p); + + ecma_deref_object (lex_env_p); + ecma_free_value (this_binding); + +#if JERRY_SNAPSHOT_EXEC + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + { + ecma_bytecode_deref (bytecode_data_p); + } +#else /* !JERRY_SNAPSHOT_EXEC */ + ecma_bytecode_deref (bytecode_data_p); +#endif /* JERRY_SNAPSHOT_EXEC */ + + return completion_value; +} /* vm_run_eval */ + +#if JERRY_MODULE_SYSTEM + +/** + * Run module code + * + * Note: + * returned value must be freed with ecma_free_value, when it is no longer needed. + * + * @return ecma value + */ +ecma_value_t +vm_run_module (ecma_module_t *module_p) /**< module to be executed */ +{ + const ecma_value_t module_init_result = ecma_module_initialize (module_p); + + if (ECMA_IS_VALUE_ERROR (module_init_result)) + { + return module_init_result; + } + + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = module_p->u.compiled_code_p; + shared.function_object_p = &module_p->header.object; + shared.status_flags = 0; + + return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p); +} /* vm_run_module */ + +#endif /* JERRY_MODULE_SYSTEM */ + +/** + * Construct object + * + * @return object value + */ +static ecma_value_t +vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ + ecma_value_t lit_value) /**< literal */ +{ + ecma_compiled_code_t *bytecode_p; + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (!(frame_ctx_p->shared_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, lit_value); +#if JERRY_SNAPSHOT_EXEC + } + else + { + uint8_t *byte_p = ((uint8_t *) frame_ctx_p->shared_p->bytecode_header_p) + lit_value; + bytecode_p = (ecma_compiled_code_t *) byte_p; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + +#if JERRY_BUILTIN_REGEXP + if (JERRY_UNLIKELY (!CBC_IS_FUNCTION (bytecode_p->status_flags))) + { + ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL); + + if (JERRY_UNLIKELY (regexp_obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + return ecma_op_create_regexp_from_bytecode (regexp_obj_p, (re_compiled_code_t *) bytecode_p); + } +#else /* !JERRY_BUILTIN_REGEXP */ + JERRY_ASSERT (CBC_IS_FUNCTION (bytecode_p->status_flags)); +#endif /* JERRY_BUILTIN_REGEXP */ + + ecma_object_t *func_obj_p; + + if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (bytecode_p->status_flags))) + { + func_obj_p = ecma_op_create_arrow_function_object (frame_ctx_p->lex_env_p, bytecode_p, frame_ctx_p->this_binding); + } + else + { + func_obj_p = ecma_op_create_any_function_object (frame_ctx_p->lex_env_p, bytecode_p); + } + + return ecma_make_object_value (func_obj_p); +} /* vm_construct_literal_object */ + +/** + * Get implicit this value + * + * @return true - if the implicit 'this' value is updated, + * false - otherwise + */ +static inline bool +vm_get_implicit_this_value (ecma_value_t *this_value_p) /**< [in,out] this value */ +{ + if (ecma_is_value_object (*this_value_p)) + { + ecma_object_t *this_obj_p = ecma_get_object_from_value (*this_value_p); + + if (ecma_is_lexical_environment (this_obj_p)) + { + ecma_value_t completion_value = ecma_op_implicit_this_value (this_obj_p); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion_value)); + + *this_value_p = completion_value; + return true; + } + } + return false; +} /* vm_get_implicit_this_value */ + +/** + * Special bytecode sequence for error handling while the vm_loop + * is preserved for an execute operation + */ +static const uint8_t vm_error_byte_code_p[] = { CBC_EXT_OPCODE, CBC_EXT_ERROR }; + +/** + * Get class function object + * + * @return the pointer to the object + */ +static ecma_object_t * +vm_get_class_function (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + JERRY_ASSERT (frame_ctx_p != NULL); + + if (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC) + { + return frame_ctx_p->shared_p->function_object_p; + } + + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p); + + JERRY_ASSERT (environment_record_p != NULL); + return ecma_get_object_from_value (environment_record_p->function_object); +} /* vm_get_class_function */ + +/** + * 'super(...)' function call handler. + */ +static void +vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + JERRY_ASSERT (frame_ctx_p->call_operation == VM_EXEC_SUPER_CALL); + JERRY_ASSERT (frame_ctx_p->byte_code_p[0] == CBC_EXT_OPCODE); + + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p + 3; + uint8_t opcode = byte_code_p[-2]; + uint32_t arguments_list_len; + + bool spread_arguments = opcode >= CBC_EXT_SPREAD_SUPER_CALL; + + ecma_collection_t *collection_p = NULL; + ecma_value_t *arguments_p; + + if (spread_arguments) + { + ecma_value_t collection = *(--frame_ctx_p->stack_top_p); + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, collection); + arguments_p = collection_p->buffer_p; + arguments_list_len = collection_p->item_count; + } + else + { + arguments_list_len = byte_code_p[-1]; + arguments_p = frame_ctx_p->stack_top_p; + } + + ecma_value_t func_value = *(--frame_ctx_p->stack_top_p); + ecma_value_t completion_value; + + ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p); + JERRY_ASSERT (environment_record_p); + + if (!ecma_is_constructor (func_value)) + { + completion_value = ecma_raise_type_error (ECMA_ERR_VALUE_FOR_CLASS_HERITAGE_IS_NOT_A_CONSTRUCTOR); + } + else + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); + completion_value = + ecma_op_function_construct (func_obj_p, JERRY_CONTEXT (current_new_target_p), arguments_p, arguments_list_len); + + if (!ECMA_IS_VALUE_ERROR (completion_value) && ecma_op_this_binding_is_initialized (environment_record_p)) + { + ecma_free_value (completion_value); + completion_value = ecma_raise_reference_error (ECMA_ERR_SUPER_CONSTRUCTOR_MAY_ONLY_BE_CALLED_ONCE); + } + } + + /* Free registers. */ + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_fast_free_value (arguments_p[i]); + } + + if (collection_p != NULL) + { + ecma_collection_destroy (collection_p); + } + + if (ecma_is_value_object (completion_value)) + { + ecma_op_bind_this_value (environment_record_p, completion_value); + frame_ctx_p->this_binding = completion_value; + + ecma_value_t fields_value = opfunc_init_class_fields (vm_get_class_function (frame_ctx_p), completion_value); + + if (ECMA_IS_VALUE_ERROR (fields_value)) + { + ecma_free_value (completion_value); + completion_value = ECMA_VALUE_ERROR; + } + } + + ecma_free_value (func_value); + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + frame_ctx_p->byte_code_p = byte_code_p; + uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode]; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (completion_value); + } + else if (opcode_data & VM_OC_PUT_STACK) + { + *frame_ctx_p->stack_top_p++ = completion_value; + } + else + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = completion_value; + } + } +} /* vm_super_call */ + +/** + * Perform one of the following call/construct operation with spreaded argument list + * - f(...args) + * - o.f(...args) + * - new O(...args) + */ +static void +vm_spread_operation (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + JERRY_ASSERT (frame_ctx_p->byte_code_p[0] == CBC_EXT_OPCODE); + + uint8_t opcode = frame_ctx_p->byte_code_p[1]; + ecma_value_t completion_value; + ecma_value_t collection = *(--frame_ctx_p->stack_top_p); + + ecma_collection_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, collection); + ecma_value_t func_value = *(--frame_ctx_p->stack_top_p); + bool is_call_prop = opcode >= CBC_EXT_SPREAD_CALL_PROP; + + if (frame_ctx_p->byte_code_p[1] == CBC_EXT_SPREAD_NEW) + { + ecma_error_msg_t constructor_message_id = ecma_check_constructor (func_value); + if (constructor_message_id != ECMA_IS_VALID_CONSTRUCTOR) + { + completion_value = ecma_raise_type_error (constructor_message_id); + } + else + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (func_value); + + completion_value = ecma_op_function_construct (constructor_obj_p, + constructor_obj_p, + collection_p->buffer_p, + collection_p->item_count); + } + } + else + { + ecma_value_t this_value = is_call_prop ? frame_ctx_p->stack_top_p[-2] : ECMA_VALUE_UNDEFINED; + + if (!ecma_is_value_object (func_value) || !ecma_op_object_is_callable (ecma_get_object_from_value (func_value))) + { + completion_value = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + } + else + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); + + completion_value = + ecma_op_function_call (func_obj_p, this_value, collection_p->buffer_p, collection_p->item_count); + } + + if (is_call_prop) + { + ecma_free_value (*(--frame_ctx_p->stack_top_p)); + ecma_free_value (*(--frame_ctx_p->stack_top_p)); + } + } + + ecma_collection_free (collection_p); + ecma_free_value (func_value); + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode]; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (completion_value); + } + else if (opcode_data & VM_OC_PUT_STACK) + { + *frame_ctx_p->stack_top_p++ = completion_value; + } + else + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = completion_value; + } + + /* EXT_OPCODE, SPREAD_OPCODE, BYTE_ARG */ + frame_ctx_p->byte_code_p += 3; + } +} /* vm_spread_operation */ + +/** + * 'Function call' opcode handler. + * + * See also: ECMA-262 v5, 11.2.3 + */ +static void +opfunc_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p + 1; + uint8_t opcode = byte_code_p[-1]; + uint32_t arguments_list_len; + + if (opcode >= CBC_CALL0) + { + arguments_list_len = (unsigned int) ((opcode - CBC_CALL0) / 6); + } + else + { + arguments_list_len = *byte_code_p++; + } + + bool is_call_prop = ((opcode - CBC_CALL) % 6) >= 3; + + ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len; + ecma_value_t this_value = is_call_prop ? stack_top_p[-3] : ECMA_VALUE_UNDEFINED; + ecma_value_t func_value = stack_top_p[-1]; + + ecma_value_t completion_value = + ecma_op_function_validated_call (func_value, this_value, stack_top_p, arguments_list_len); + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; + + /* Free registers. */ + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_fast_free_value (stack_top_p[i]); + } + + if (is_call_prop) + { + ecma_free_value (*(--stack_top_p)); + ecma_free_value (*(--stack_top_p)); + } + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + frame_ctx_p->byte_code_p = byte_code_p; + ecma_free_value (*(--stack_top_p)); + uint32_t opcode_data = vm_decode_table[opcode]; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (completion_value); + } + else if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = completion_value; + } + else + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = completion_value; + } + } + + frame_ctx_p->stack_top_p = stack_top_p; +} /* opfunc_call */ + +/** + * 'Constructor call' opcode handler. + * + * See also: ECMA-262 v5, 11.2.2 + */ +static void +opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p + 1; + uint8_t opcode = byte_code_p[-1]; + unsigned int arguments_list_len; + + if (opcode >= CBC_NEW0) + { + arguments_list_len = (unsigned int) (opcode - CBC_NEW0); + } + else + { + arguments_list_len = *byte_code_p++; + } + + ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len; + ecma_value_t constructor_value = stack_top_p[-1]; + ecma_value_t completion_value; + + ecma_error_msg_t constructor_message_id = ecma_check_constructor (constructor_value); + if (constructor_message_id != ECMA_IS_VALID_CONSTRUCTOR) + { + completion_value = ecma_raise_type_error (constructor_message_id); + } + else + { + ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor_value); + + completion_value = + ecma_op_function_construct (constructor_obj_p, constructor_obj_p, stack_top_p, arguments_list_len); + } + + /* Free registers. */ + for (uint32_t i = 0; i < arguments_list_len; i++) + { + ecma_fast_free_value (stack_top_p[i]); + } + + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (completion_value))) + { + frame_ctx_p->byte_code_p = (uint8_t *) vm_error_byte_code_p; + } + else + { + ecma_free_value (stack_top_p[-1]); + frame_ctx_p->byte_code_p = byte_code_p; + stack_top_p[-1] = completion_value; + } + + frame_ctx_p->stack_top_p = stack_top_p; +} /* opfunc_construct */ + +/** + * Read literal index from the byte code stream into destination. + * + * @param destination destination + */ +#define READ_LITERAL_INDEX(destination) \ + do \ + { \ + (destination) = *byte_code_p++; \ + if ((destination) >= encoding_limit) \ + { \ + (destination) = (uint16_t) ((((destination) << 8) | *byte_code_p++) - encoding_delta); \ + } \ + } while (0) + +/** + * Get literal value by literal index. + * + * @param literal_index literal index + * @param target_value target value + * + * TODO: For performance reasons, we define this as a macro. + * When we are able to construct a function with similar speed, + * we can remove this macro. + */ +#define READ_LITERAL(literal_index, target_value) \ + do \ + { \ + if ((literal_index) < ident_end) \ + { \ + if ((literal_index) < register_end) \ + { \ + /* Note: There should be no specialization for arguments. */ \ + (target_value) = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); \ + } \ + else \ + { \ + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); \ + \ + result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, name_p); \ + \ + if (ECMA_IS_VALUE_ERROR (result)) \ + { \ + goto error; \ + } \ + (target_value) = result; \ + } \ + } \ + else if (literal_index < const_literal_end) \ + { \ + (target_value) = ecma_fast_copy_value (literal_start_p[literal_index]); \ + } \ + else \ + { \ + /* Object construction. */ \ + (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \ + } \ + } while (0) + +/** + * Store the original value for post increase/decrease operators + * + * @param value original value + */ +#define POST_INCREASE_DECREASE_PUT_RESULT(value) \ + if (opcode_data & VM_OC_PUT_STACK) \ + { \ + if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG) \ + { \ + JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT || opcode == CBC_POST_DECR_IDENT_PUSH_RESULT); \ + *stack_top_p++ = (value); \ + } \ + else \ + { \ + /* The parser ensures there is enough space for the \ + * extra value on the stack. See js-parser-expr.c. */ \ + JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT || opcode == CBC_POST_DECR_PUSH_RESULT); \ + stack_top_p++; \ + stack_top_p[-1] = stack_top_p[-2]; \ + stack_top_p[-2] = stack_top_p[-3]; \ + stack_top_p[-3] = (value); \ + } \ + opcode_data &= (uint32_t) ~VM_OC_PUT_STACK; \ + } \ + else \ + { \ + JERRY_ASSERT (opcode_data &VM_OC_PUT_BLOCK); \ + ecma_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); \ + VM_GET_REGISTERS (frame_ctx_p)[0] = (value); \ + opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK; \ + } + +/** + * Get the end of the existing topmost context + */ +#define VM_LAST_CONTEXT_END() (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth) + +/** + * Run generic byte code. + * + * @return ecma value + */ +static ecma_value_t JERRY_ATTR_NOINLINE +vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; + const uint8_t *byte_code_p = frame_ctx_p->byte_code_p; + ecma_value_t *literal_start_p = frame_ctx_p->literal_start_p; + + ecma_value_t *stack_top_p; + uint16_t encoding_limit; + uint16_t encoding_delta; + uint16_t register_end; + uint16_t ident_end; + uint16_t const_literal_end; + int32_t branch_offset = 0; + uint8_t branch_offset_length = 0; + ecma_value_t left_value; + ecma_value_t right_value; + ecma_value_t result = ECMA_VALUE_EMPTY; + bool is_strict = ((bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); + + /* Prepare for byte code execution. */ + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) (bytecode_header_p); + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) (bytecode_header_p); + register_end = args_p->register_end; + ident_end = args_p->ident_end; + const_literal_end = args_p->const_literal_end; + } + + stack_top_p = frame_ctx_p->stack_top_p; + + /* Outer loop for exception handling. */ + while (true) + { + /* Internal loop for byte code execution. */ + while (true) + { + const uint8_t *byte_code_start_p = byte_code_p; + uint8_t opcode = *byte_code_p++; + uint32_t opcode_data = opcode; + + if (opcode == CBC_EXT_OPCODE) + { + opcode = *byte_code_p++; + opcode_data = (uint32_t) ((CBC_END + 1) + opcode); + } + + opcode_data = vm_decode_table[opcode_data]; + + left_value = ECMA_VALUE_UNDEFINED; + right_value = ECMA_VALUE_UNDEFINED; + + uint32_t operands = VM_OC_GET_ARGS_INDEX (opcode_data); + + if (operands >= VM_OC_GET_LITERAL) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + READ_LITERAL (literal_index, left_value); + + if (operands != VM_OC_GET_LITERAL) + { + switch (operands) + { + case VM_OC_GET_LITERAL_LITERAL: + { + uint16_t second_literal_index; + READ_LITERAL_INDEX (second_literal_index); + READ_LITERAL (second_literal_index, right_value); + break; + } + case VM_OC_GET_STACK_LITERAL: + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + right_value = left_value; + left_value = *(--stack_top_p); + break; + } + default: + { + JERRY_ASSERT (operands == VM_OC_GET_THIS_LITERAL); + + right_value = left_value; + left_value = ecma_copy_value (frame_ctx_p->this_binding); + break; + } + } + } + } + else if (operands >= VM_OC_GET_STACK) + { + JERRY_ASSERT (operands == VM_OC_GET_STACK || operands == VM_OC_GET_STACK_STACK); + + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + left_value = *(--stack_top_p); + + if (operands == VM_OC_GET_STACK_STACK) + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + right_value = left_value; + left_value = *(--stack_top_p); + } + } + else if (operands == VM_OC_GET_BRANCH) + { + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode); + JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3); + + branch_offset = *(byte_code_p++); + + if (JERRY_UNLIKELY (branch_offset_length != 1)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + + if (JERRY_UNLIKELY (branch_offset_length == 3)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + } + } + + if (opcode_data & VM_OC_BACKWARD_BRANCH) + { +#if JERRY_VM_HALT + if (JERRY_CONTEXT (vm_exec_stop_cb) != NULL && --JERRY_CONTEXT (vm_exec_stop_counter) == 0) + { + result = JERRY_CONTEXT (vm_exec_stop_cb) (JERRY_CONTEXT (vm_exec_stop_user_p)); + + if (ecma_is_value_undefined (result)) + { + JERRY_CONTEXT (vm_exec_stop_counter) = JERRY_CONTEXT (vm_exec_stop_frequency); + } + else + { + JERRY_CONTEXT (vm_exec_stop_counter) = 1; + + if (ecma_is_value_exception (result)) + { + ecma_throw_exception (result); + } + else + { + jcontext_raise_exception (result); + } + + JERRY_ASSERT (jcontext_has_pending_exception ()); + jcontext_set_abort_flag (true); + result = ECMA_VALUE_ERROR; + goto error; + } + } +#endif /* JERRY_VM_HALT */ + + branch_offset = -branch_offset; + } + } + + switch (VM_OC_GROUP_GET_INDEX (opcode_data)) + { + case VM_OC_POP: + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + ecma_free_value (*(--stack_top_p)); + continue; + } + case VM_OC_POP_BLOCK: + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = *(--stack_top_p); + continue; + } + case VM_OC_PUSH: + { + *stack_top_p++ = left_value; + continue; + } + case VM_OC_PUSH_TWO: + { + *stack_top_p++ = left_value; + *stack_top_p++ = right_value; + continue; + } + case VM_OC_PUSH_THREE: + { + uint16_t literal_index; + + *stack_top_p++ = left_value; + left_value = ECMA_VALUE_UNDEFINED; + + READ_LITERAL_INDEX (literal_index); + READ_LITERAL (literal_index, left_value); + + *stack_top_p++ = right_value; + *stack_top_p++ = left_value; + continue; + } + case VM_OC_PUSH_UNDEFINED: + { + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + continue; + } + case VM_OC_PUSH_TRUE: + { + *stack_top_p++ = ECMA_VALUE_TRUE; + continue; + } + case VM_OC_PUSH_FALSE: + { + *stack_top_p++ = ECMA_VALUE_FALSE; + continue; + } + case VM_OC_PUSH_NULL: + { + *stack_top_p++ = ECMA_VALUE_NULL; + continue; + } + case VM_OC_PUSH_THIS: + { + *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding); + continue; + } + case VM_OC_PUSH_0: + { + *stack_top_p++ = ecma_make_integer_value (0); + continue; + } + case VM_OC_PUSH_POS_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + *stack_top_p++ = ecma_make_integer_value (number + 1); + continue; + } + case VM_OC_PUSH_NEG_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + *stack_top_p++ = ecma_make_integer_value (-(number + 1)); + continue; + } + case VM_OC_PUSH_LIT_0: + { + stack_top_p[0] = left_value; + stack_top_p[1] = ecma_make_integer_value (0); + stack_top_p += 2; + continue; + } + case VM_OC_PUSH_LIT_POS_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + stack_top_p[0] = left_value; + stack_top_p[1] = ecma_make_integer_value (number + 1); + stack_top_p += 2; + continue; + } + case VM_OC_PUSH_LIT_NEG_BYTE: + { + ecma_integer_value_t number = *byte_code_p++; + stack_top_p[0] = left_value; + stack_top_p[1] = ecma_make_integer_value (-(number + 1)); + stack_top_p += 2; + continue; + } + case VM_OC_PUSH_OBJECT: + { + ecma_object_t *obj_p = + ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); + + *stack_top_p++ = ecma_make_object_value (obj_p); + continue; + } + case VM_OC_PUSH_NAMED_FUNC_EXPR: + { + ecma_object_t *func_p = ecma_get_object_from_value (left_value); + + JERRY_ASSERT (ecma_get_object_type (func_p) == ECMA_OBJECT_TYPE_FUNCTION); + + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; + + JERRY_ASSERT (frame_ctx_p->lex_env_p + == ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp)); + + ecma_object_t *name_lex_env = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); + + ecma_op_create_immutable_binding (name_lex_env, ecma_get_string_from_value (right_value), left_value); + + ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, name_lex_env, 0); + + ecma_free_value (right_value); + ecma_deref_object (name_lex_env); + *stack_top_p++ = left_value; + continue; + } + case VM_OC_CREATE_BINDING: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (opcode == CBC_CREATE_LET) + { + prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE; + } + else if (opcode == CBC_CREATE_CONST) + { + prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE; + } + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL); + + if (opcode != CBC_CREATE_VAR) + { + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + } + + continue; + } + case VM_OC_VAR_EVAL: + { + uint32_t literal_index; + ecma_value_t lit_value = ECMA_VALUE_UNDEFINED; + + if (opcode == CBC_CREATE_VAR_FUNC_EVAL) + { + uint32_t value_index; + READ_LITERAL_INDEX (value_index); + JERRY_ASSERT (value_index >= const_literal_end); + + lit_value = vm_construct_literal_object (frame_ctx_p, literal_start_p[value_index]); + } + + READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { +#if !(defined JERRY_NDEBUG) + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + +#if !(defined JERRY_NDEBUG) + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + /* 'Variable declaration' */ + result = ecma_op_has_binding (lex_env_p, name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } +#endif /* JERRY_BUILTIN_PROXY */ + + ecma_property_t *prop_p = NULL; + + if (ecma_is_value_false (result)) + { + bool is_configurable = (frame_ctx_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL) != 0; + prop_p = ecma_op_create_mutable_binding (lex_env_p, name_p, is_configurable); + + if (JERRY_UNLIKELY (prop_p == ECMA_PROPERTY_POINTER_ERROR)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + } + + if (lit_value != ECMA_VALUE_UNDEFINED) + { + JERRY_ASSERT (ecma_is_value_object (lit_value)); + + if (prop_p != NULL) + { + JERRY_ASSERT (ecma_is_value_undefined (ECMA_PROPERTY_VALUE_PTR (prop_p)->value)); + JERRY_ASSERT (ecma_is_property_writable (*prop_p)); + ECMA_PROPERTY_VALUE_PTR (prop_p)->value = lit_value; + ecma_free_object (lit_value); + } + else + { + result = ecma_op_put_value_lex_env_base (lex_env_p, name_p, is_strict, lit_value); + ecma_free_object (lit_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + } + } + continue; + } + case VM_OC_EXT_VAR_EVAL: + { + uint32_t literal_index; + ecma_value_t lit_value = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); + + if (opcode == CBC_EXT_CREATE_VAR_FUNC_EVAL) + { + uint32_t value_index; + READ_LITERAL_INDEX (value_index); + JERRY_ASSERT (value_index >= const_literal_end); + + lit_value = vm_construct_literal_object (frame_ctx_p, literal_start_p[value_index]); + } + + READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + ecma_object_t *prev_lex_env_p = NULL; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { +#if !(defined JERRY_NDEBUG) + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + prev_lex_env_p = lex_env_p; + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (prev_lex_env_p != NULL + && ecma_get_lex_env_type (prev_lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + ecma_property_t *property_p = ecma_find_named_property (prev_lex_env_p, name_p); + ecma_property_value_t *property_value_p; + + if (property_p == NULL) + { + property_value_p = + ecma_create_named_data_property (prev_lex_env_p, name_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, NULL); + + if (lit_value == ECMA_VALUE_UNDEFINED) + { + continue; + } + } + else + { + if (lit_value == ECMA_VALUE_UNDEFINED) + { + continue; + } + + property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + ecma_free_value_if_not_object (property_value_p->value); + } + + property_value_p->value = lit_value; + ecma_deref_object (ecma_get_object_from_value (lit_value)); + continue; + } + case VM_OC_CREATE_ARGUMENTS: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); + + result = ecma_op_create_arguments_object ((vm_frame_ctx_shared_args_t *) (frame_ctx_p->shared_p), + frame_ctx_p->lex_env_p); + + if (literal_index < register_end) + { + JERRY_ASSERT (VM_GET_REGISTER (frame_ctx_p, literal_index) == ECMA_VALUE_UNDEFINED); + VM_GET_REGISTER (frame_ctx_p, literal_index) = result; + continue; + } + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + ecma_property_value_t *property_value_p; + + property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL); + property_value_p->value = result; + + ecma_deref_object (ecma_get_object_from_value (result)); + continue; + } +#if JERRY_SNAPSHOT_EXEC + case VM_OC_SET_BYTECODE_PTR: + { + memcpy (&byte_code_p, byte_code_p++, sizeof (uintptr_t)); + frame_ctx_p->byte_code_start_p = byte_code_p; + continue; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + case VM_OC_INIT_ARG_OR_FUNC: + { + uint32_t literal_index, value_index; + ecma_value_t lit_value; + bool release = false; + + READ_LITERAL_INDEX (value_index); + + if (value_index < register_end) + { + /* Take (not copy) the reference. */ + lit_value = ecma_copy_value_if_not_object (VM_GET_REGISTER (frame_ctx_p, value_index)); + } + else + { + lit_value = vm_construct_literal_object (frame_ctx_p, literal_start_p[value_index]); + release = true; + } + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (value_index != literal_index); + JERRY_ASSERT (value_index >= register_end || literal_index >= register_end); + + if (literal_index < register_end) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + JERRY_ASSERT (release); + VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value; + continue; + } + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + ecma_property_value_t *property_value_p; + property_value_p = + ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + property_value_p->value = lit_value; + + if (release) + { + ecma_deref_object (ecma_get_object_from_value (lit_value)); + } + continue; + } + case VM_OC_CHECK_VAR: + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) + == CBC_FUNCTION_SCRIPT); + + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + if ((frame_ctx_p->lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) == 0) + { + continue; + } + + ecma_string_t *const literal_name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_property_t *const binding_p = ecma_find_named_property (frame_ctx_p->lex_env_p, literal_name_p); + + if (binding_p != NULL) + { + result = ecma_raise_syntax_error (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED); + goto error; + } + + continue; + } + case VM_OC_CHECK_LET: + { + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) + == CBC_FUNCTION_SCRIPT); + + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *literal_name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + + if (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { + result = opfunc_lexical_scope_has_restricted_binding (frame_ctx_p, literal_name_p); + + if (!ecma_is_value_false (result)) + { + if (ecma_is_value_true (result)) + { + result = ecma_raise_syntax_error (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED); + } + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); + goto error; + } + + continue; + } + + result = ecma_op_has_binding (lex_env_p, literal_name_p); + +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_true (result)) + { + result = ecma_raise_syntax_error (ECMA_ERR_LOCAL_VARIABLE_IS_REDECLARED); + goto error; + } + + continue; + } + case VM_OC_ASSIGN_LET_CONST: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index >= register_end); + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE + || (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS + && ECMA_LEX_ENV_CLASS_IS_MODULE (frame_ctx_p->lex_env_p))); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_property_t *property_p = ecma_find_named_property (frame_ctx_p->lex_env_p, name_p); + + JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p) + && (*property_p & ECMA_PROPERTY_FLAG_DATA)); + JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p)->value == ECMA_VALUE_UNINITIALIZED); + + ECMA_PROPERTY_VALUE_PTR (property_p)->value = left_value; + + if (ecma_is_value_object (left_value)) + { + ecma_deref_object (ecma_get_object_from_value (left_value)); + } + continue; + } + case VM_OC_INIT_BINDING: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (opcode == CBC_INIT_LET) + { + prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE; + } + else if (opcode == CBC_INIT_CONST) + { + prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE; + } + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + + ecma_value_t value = *(--stack_top_p); + + property_value_p->value = value; + ecma_deref_if_object (value); + continue; + } + case VM_OC_THROW_CONST_ERROR: + { + result = ecma_raise_type_error (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED); + goto error; + } + case VM_OC_COPY_TO_GLOBAL: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { +#ifndef JERRY_NDEBUG + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + ecma_property_value_t *prop_value_p; + + if (property_p == NULL) + { + prop_value_p = ecma_create_named_data_property (lex_env_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + } + else + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); +#endif /* !JERRY_NDEBUG */ + prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + } + + ecma_named_data_property_assign_value (lex_env_p, prop_value_p, left_value); + } + else + { + result = ecma_op_set_mutable_binding (lex_env_p, name_p, left_value, is_strict); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + } + + goto free_left_value; + } + case VM_OC_COPY_FROM_ARG: + { + uint32_t literal_index; + READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + ecma_object_t *arg_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + + JERRY_ASSERT ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + && ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (arg_lex_env_p != NULL && !(arg_lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + && ecma_get_lex_env_type (arg_lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (lex_env_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + ecma_property_t *property_p = ecma_find_named_property (arg_lex_env_p, name_p); + JERRY_ASSERT (property_p != NULL); + + ecma_property_value_t *arg_prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + property_value_p->value = ecma_copy_value_if_not_object (arg_prop_value_p->value); + continue; + } + case VM_OC_CLONE_CONTEXT: + { + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); + + bool copy_values = (byte_code_start_p[1] == CBC_EXT_CLONE_FULL_CONTEXT); + frame_ctx_p->lex_env_p = ecma_clone_decl_lexical_environment (frame_ctx_p->lex_env_p, copy_values); + continue; + } + case VM_OC_SET__PROTO__: + { + result = ecma_builtin_object_object_set_proto (stack_top_p[-1], left_value); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_CLASS_CALL_STATIC_BLOCK: + { + result = ecma_op_function_call (ecma_get_object_from_value (left_value), frame_ctx_p->this_binding, NULL, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_PUSH_STATIC_FIELD_FUNC: + { + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE + && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_FIELD_FUNC + || byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC)); + + bool push_computed = (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC); + ecma_value_t value = stack_top_p[-1]; + + if (!push_computed) + { + stack_top_p++; + } + + memmove (stack_top_p - 3, stack_top_p - 4, 3 * sizeof (ecma_value_t)); + stack_top_p[-4] = left_value; + + ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]); + ecma_object_t *initializer_func_p = ecma_get_object_from_value (left_value); + opfunc_bind_class_environment (frame_ctx_p->lex_env_p, class_object_p, class_object_p, initializer_func_p); + + if (!push_computed) + { + continue; + } + + left_value = value; + /* FALLTHRU */ + } + case VM_OC_ADD_COMPUTED_FIELD: + { + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE + && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC + || byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD + || byte_code_start_p[1] == CBC_EXT_ADD_STATIC_COMPUTED_FIELD)); + + int index = (byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD) ? -2 : -4; + result = opfunc_add_computed_field (stack_top_p[index], left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_COPY_DATA_PROPERTIES: + { + left_value = *(--stack_top_p); + + if (ecma_is_value_undefined (left_value) || ecma_is_value_null (left_value)) + { + continue; + } + + result = opfunc_copy_data_properties (stack_top_p[-1], left_value, ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_left_value; + } + case VM_OC_SET_COMPUTED_PROPERTY: + { + /* Swap values. */ + left_value ^= right_value; + right_value ^= left_value; + left_value ^= right_value; + /* FALLTHRU */ + } + case VM_OC_SET_PROPERTY: + { + JERRY_STATIC_ASSERT ((VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH), + vm_oc_non_static_flag_must_be_equal_to_vm_oc_backward_branch); + + JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1); + + ecma_string_t *prop_name_p = ecma_op_to_property_key (right_value); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + && !(opcode_data & VM_OC_NON_STATIC_FLAG)) + { + result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); + goto error; + } + + const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2; + + ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]); + + opfunc_set_data_property (object_p, prop_name_p, left_value); + ecma_deref_ecma_string (prop_name_p); + + goto free_both_values; + } + case VM_OC_SET_GETTER: + case VM_OC_SET_SETTER: + { + JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1); + + ecma_string_t *prop_name_p = ecma_op_to_property_key (left_value); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + && !(opcode_data & VM_OC_NON_STATIC_FLAG)) + { + result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); + goto error; + } + + const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2; + opfunc_set_accessor (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_SET_GETTER, + stack_top_p[index], + prop_name_p, + right_value); + + ecma_deref_ecma_string (prop_name_p); + + goto free_both_values; + } + case VM_OC_PUSH_ARRAY: + { + /* Note: this operation cannot throw an exception */ + *stack_top_p++ = ecma_make_object_value (ecma_op_new_array_object (0)); + continue; + } + case VM_OC_LOCAL_EVAL: + { + ECMA_CLEAR_LOCAL_PARSE_OPTS (); + uint8_t parse_opts = *byte_code_p++; + ECMA_SET_LOCAL_PARSE_OPTS (parse_opts); + continue; + } + case VM_OC_SUPER_CALL: + { + uint8_t arguments_list_len = *byte_code_p++; + + if (opcode >= CBC_EXT_SPREAD_SUPER_CALL) + { + stack_top_p -= arguments_list_len; + ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len); + + if (JERRY_UNLIKELY (arguments_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + stack_top_p++; + ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p); + } + else + { + stack_top_p -= arguments_list_len; + } + + frame_ctx_p->call_operation = VM_EXEC_SUPER_CALL; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_PUSH_CLASS_ENVIRONMENT: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + opfunc_push_class_environment (frame_ctx_p, &stack_top_p, literal_start_p[literal_index]); + continue; + } + case VM_OC_PUSH_IMPLICIT_CTOR: + { + *stack_top_p++ = opfunc_create_implicit_class_constructor (opcode, frame_ctx_p->shared_p->bytecode_header_p); + continue; + } + case VM_OC_DEFINE_FIELD: + { + result = opfunc_define_field (frame_ctx_p->this_binding, right_value, left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_both_values; + } + case VM_OC_ASSIGN_PRIVATE: + { + result = opfunc_private_set (stack_top_p[-3], stack_top_p[-2], stack_top_p[-1]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (stack_top_p[-3]); + ecma_free_value (stack_top_p[-2]); + ecma_free_value (stack_top_p[-1]); + stack_top_p -= 3; + + if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = result; + } + else if (opcode_data & VM_OC_PUT_BLOCK) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = result; + } + else + { + ecma_free_value (result); + } + + goto free_both_values; + } + case VM_OC_PRIVATE_FIELD_ADD: + { + result = opfunc_private_field_add (frame_ctx_p->this_binding, right_value, left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_both_values; + } + case VM_OC_PRIVATE_PROP_GET: + { + result = opfunc_private_get (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_PRIVATE_PROP_REFERENCE: + { + result = opfunc_private_get (stack_top_p[-1], left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = left_value; + *stack_top_p++ = result; + continue; + } + case VM_OC_PRIVATE_IN: + { + result = opfunc_private_in (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_COLLECT_PRIVATE_PROPERTY: + { + opfunc_collect_private_properties (stack_top_p[-2], left_value, right_value, opcode); + continue; + } + case VM_OC_INIT_CLASS: + { + result = opfunc_init_class (frame_ctx_p, stack_top_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + continue; + } + case VM_OC_FINALIZE_CLASS: + { + JERRY_ASSERT (opcode == CBC_EXT_FINALIZE_NAMED_CLASS || opcode == CBC_EXT_FINALIZE_ANONYMOUS_CLASS); + + if (opcode == CBC_EXT_FINALIZE_NAMED_CLASS) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + left_value = literal_start_p[literal_index]; + } + + opfunc_finalize_class (frame_ctx_p, &stack_top_p, left_value); + continue; + } + case VM_OC_SET_FIELD_INIT: + { + ecma_string_t *property_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT); + ecma_object_t *proto_object_p = ecma_get_object_from_value (stack_top_p[-1]); + ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]); + ecma_object_t *initializer_func_p = ecma_get_object_from_value (left_value); + + opfunc_bind_class_environment (frame_ctx_p->lex_env_p, proto_object_p, class_object_p, initializer_func_p); + + ecma_property_value_t *property_value_p = + ecma_create_named_data_property (class_object_p, property_name_p, ECMA_PROPERTY_FIXED, NULL); + property_value_p->value = left_value; + + property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); + ecma_property_t *property_p = ecma_find_named_property (class_object_p, property_name_p); + + if (property_p != NULL) + { + property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + ecma_value_t *compact_collection_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, property_value_p->value); + compact_collection_p = ecma_compact_collection_shrink (compact_collection_p); + ECMA_SET_INTERNAL_VALUE_POINTER (property_value_p->value, compact_collection_p); + } + + goto free_left_value; + } + case VM_OC_RUN_FIELD_INIT: + { + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); + result = opfunc_init_class_fields (frame_ctx_p->shared_p->function_object_p, frame_ctx_p->this_binding); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + continue; + } + case VM_OC_RUN_STATIC_FIELD_INIT: + { + left_value = stack_top_p[-2]; + stack_top_p[-2] = stack_top_p[-1]; + stack_top_p--; + + result = opfunc_init_static_class_fields (left_value, stack_top_p[-1]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + goto free_left_value; + } + case VM_OC_SET_NEXT_COMPUTED_FIELD: + { + ecma_integer_value_t next_index = ecma_get_integer_from_value (stack_top_p[-2]) + 1; + stack_top_p[-2] = ecma_make_integer_value (next_index); + + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS); + + ecma_value_t *computed_class_fields_p = VM_GET_COMPUTED_CLASS_FIELDS (frame_ctx_p); + JERRY_ASSERT ((ecma_value_t) next_index < ECMA_COMPACT_COLLECTION_GET_SIZE (computed_class_fields_p)); + ecma_value_t prop_name = computed_class_fields_p[next_index]; + + if (opcode == CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC) + { + ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + + JERRY_ASSERT (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) == NULL); + ecma_property_value_t *value_p; + value_p = ecma_create_named_data_property (func_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); + } + + value_p->value = ecma_copy_value (prop_name); + } + + result = opfunc_define_field (frame_ctx_p->this_binding, prop_name, stack_top_p[-1]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (*(--stack_top_p)); + continue; + } + case VM_OC_PUSH_SUPER_CONSTRUCTOR: + { + result = ecma_op_function_get_super_constructor (vm_get_class_function (frame_ctx_p)); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + continue; + } + case VM_OC_RESOLVE_LEXICAL_THIS: + { + result = ecma_op_get_this_binding (frame_ctx_p->lex_env_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + continue; + } + case VM_OC_OBJECT_LITERAL_HOME_ENV: + { + if (opcode == CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT) + { + ecma_value_t obj_value = stack_top_p[-1]; + ecma_object_t *obj_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0); + + ECMA_SET_NON_NULL_POINTER (obj_env_p->u1.bound_object_cp, ecma_get_object_from_value (obj_value)); + stack_top_p[-1] = ecma_make_object_value (obj_env_p); + *stack_top_p++ = obj_value; + } + else + { + JERRY_ASSERT (opcode == CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT); + ecma_deref_object (ecma_get_object_from_value (stack_top_p[-2])); + stack_top_p[-2] = stack_top_p[-1]; + stack_top_p--; + } + continue; + } + case VM_OC_SET_HOME_OBJECT: + { + int offset = opcode == CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED ? -1 : 0; + opfunc_set_home_object (ecma_get_object_from_value (stack_top_p[-1]), + ecma_get_object_from_value (stack_top_p[-3 + offset])); + continue; + } + case VM_OC_SUPER_REFERENCE: + { + result = opfunc_form_super_reference (&stack_top_p, frame_ctx_p, left_value, opcode); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + goto free_left_value; + } + case VM_OC_SET_FUNCTION_NAME: + { + const char *prefix_p = NULL; + lit_utf8_size_t prefix_size = 0; + + if (opcode != CBC_EXT_SET_FUNCTION_NAME) + { + ecma_value_t prop_name_value; + + if (opcode == CBC_EXT_SET_CLASS_NAME) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + prop_name_value = literal_start_p[literal_index]; + } + else + { + prop_name_value = stack_top_p[-2]; + } + + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name_value); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + left_value = ecma_make_prop_name_value (prop_name_p); + + if (opcode != CBC_EXT_SET_CLASS_NAME) + { + ecma_ref_ecma_string (prop_name_p); + ecma_free_value (stack_top_p[-2]); + stack_top_p[-2] = left_value; + } + + if (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME || opcode == CBC_EXT_SET_COMPUTED_SETTER_NAME) + { + prefix_p = (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME) ? "get " : "set "; + prefix_size = 4; + } + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + + if (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) != NULL) + { + ecma_free_value (left_value); + continue; + } + + ecma_property_value_t *value_p; + value_p = ecma_create_named_data_property (func_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); + } + + value_p->value = + ecma_op_function_form_name (ecma_get_prop_name_from_value (left_value), (char*) prefix_p, prefix_size); + ecma_free_value (left_value); + continue; + } + case VM_OC_PUSH_SPREAD_ELEMENT: + { + *stack_top_p++ = ECMA_VALUE_SPREAD_ELEMENT; + continue; + } + case VM_OC_PUSH_REST_OBJECT: + { + vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p; + + JERRY_ASSERT (shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); + + const ecma_value_t *arg_list_p = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_p; + uint32_t arg_list_len = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_len; + uint16_t argument_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + argument_end = ((cbc_uint16_arguments_t *) bytecode_header_p)->argument_end; + } + else + { + argument_end = ((cbc_uint8_arguments_t *) bytecode_header_p)->argument_end; + } + + if (arg_list_len < argument_end) + { + arg_list_len = argument_end; + } + + result = ecma_op_new_array_object_from_buffer (arg_list_p + argument_end, arg_list_len - argument_end); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (result)); + *stack_top_p++ = result; + continue; + } + case VM_OC_ITERATOR_CONTEXT_CREATE: + { + result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, &left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + uint32_t context_size = + (uint32_t) (stack_top_p + PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION - VM_LAST_CONTEXT_END ()); + stack_top_p += PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION; + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size); + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_ITERATOR, context_size) | VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = result; + stack_top_p[-3] = left_value; + + continue; + } + case VM_OC_ITERATOR_STEP: + { + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + + ecma_value_t iterator = last_context_end_p[-2]; + ecma_value_t next_method = last_context_end_p[-3]; + + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + goto error; + } + + ecma_value_t value = ECMA_VALUE_UNDEFINED; + + if (!ecma_is_value_false (result)) + { + value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (value)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = value; + goto error; + } + } + else + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + } + + *stack_top_p++ = value; + continue; + } + case VM_OC_ITERATOR_CONTEXT_END: + { + JERRY_ASSERT (VM_LAST_CONTEXT_END () == stack_top_p); + + if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR) + { + stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = ecma_op_iterator_close (stack_top_p[-2]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + } + + stack_top_p = + vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION); + continue; + } + case VM_OC_DEFAULT_INITIALIZER: + { + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + + if (stack_top_p[-1] != ECMA_VALUE_UNDEFINED) + { + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + + stack_top_p--; + continue; + } + case VM_OC_REST_INITIALIZER: + { + ecma_object_t *array_p = ecma_op_new_array_object (0); + JERRY_ASSERT (ecma_op_object_is_fast_array (array_p)); + + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + ecma_value_t iterator = last_context_end_p[-2]; + ecma_value_t next_method = last_context_end_p[-3]; + uint32_t index = 0; + + while (true) + { + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + ecma_deref_object (array_p); + goto error; + } + + if (ecma_is_value_false (result)) + { + last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + break; + } + + ecma_value_t value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (value)) + { + ecma_deref_object (array_p); + result = value; + goto error; + } + + bool set_result = ecma_fast_array_set_property (array_p, index++, value); + JERRY_ASSERT (set_result); + ecma_free_value (value); + } + + *stack_top_p++ = ecma_make_object_value (array_p); + continue; + } + case VM_OC_OBJ_INIT_CONTEXT_CREATE: + { + left_value = stack_top_p[-1]; + vm_stack_context_type_t context_type = VM_CONTEXT_OBJ_INIT; + uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION; + + if (opcode == CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE) + { + context_type = VM_CONTEXT_OBJ_INIT_REST; + context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION; + } + + uint32_t context_size = (uint32_t) (stack_top_p + context_stack_allocation - VM_LAST_CONTEXT_END ()); + stack_top_p += context_stack_allocation; + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size); + + stack_top_p[-1] = VM_CREATE_CONTEXT (context_type, context_size); + stack_top_p[-2] = left_value; + + if (context_type == VM_CONTEXT_OBJ_INIT_REST) + { + stack_top_p[-3] = ecma_make_object_value (ecma_op_new_array_object (0)); + } + continue; + } + case VM_OC_OBJ_INIT_CONTEXT_END: + { + JERRY_ASSERT (stack_top_p == VM_LAST_CONTEXT_END ()); + + uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION; + + if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_OBJ_INIT_REST) + { + context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION; + } + + stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, context_stack_allocation); + continue; + } + case VM_OC_OBJ_INIT_PUSH_REST: + { + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + if (!ecma_op_require_object_coercible (last_context_end_p[-2])) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + ecma_object_t *result_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + left_value = ecma_make_object_value (result_object_p); + result = opfunc_copy_data_properties (left_value, last_context_end_p[-2], last_context_end_p[-3]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (last_context_end_p[-3]); + last_context_end_p[-3] = last_context_end_p[-2]; + last_context_end_p[-2] = ECMA_VALUE_UNDEFINED; + + *stack_top_p++ = left_value; + continue; + } + case VM_OC_INITIALIZER_PUSH_NAME: + { + if (JERRY_UNLIKELY (!ecma_is_value_prop_name (left_value))) + { + ecma_string_t *property_key = ecma_op_to_property_key (left_value); + + if (property_key == NULL) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + ecma_free_value (left_value); + left_value = ecma_make_string_value (property_key); + } + + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + ecma_object_t *array_obj_p = ecma_get_object_from_value (last_context_end_p[-3]); + JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; + ecma_fast_array_set_property (array_obj_p, ext_array_obj_p->u.array.length, left_value); + /* FALLTHRU */ + } + case VM_OC_INITIALIZER_PUSH_PROP: + { + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); + ecma_value_t base = last_context_end_p[-2]; + + if (opcode == CBC_EXT_INITIALIZER_PUSH_PROP) + { + left_value = *last_context_end_p++; + while (last_context_end_p < stack_top_p) + { + last_context_end_p[-1] = *last_context_end_p; + last_context_end_p++; + } + stack_top_p--; + } + + result = vm_op_get_value (base, left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_SPREAD_ARGUMENTS: + { + uint8_t arguments_list_len = *byte_code_p++; + stack_top_p -= arguments_list_len; + + ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len); + + if (JERRY_UNLIKELY (arguments_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + stack_top_p++; + ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p); + + frame_ctx_p->call_operation = VM_EXEC_SPREAD_OP; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_CREATE_GENERATOR: + { + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + + vm_executable_object_t *executable_object_p; + executable_object_p = opfunc_create_executable_object (frame_ctx_p, VM_CREATE_EXECUTABLE_OBJECT_GENERATOR); + + return ecma_make_object_value ((ecma_object_t *) executable_object_p); + } + case VM_OC_YIELD: + { + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = --stack_top_p; + return *stack_top_p; + } + case VM_OC_ASYNC_YIELD: + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + opfunc_async_generator_yield (async_generator_object_p, stack_top_p[-1]); + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = --stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_ASYNC_YIELD_ITERATOR: + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + JERRY_ASSERT ( + !(async_generator_object_p->u.cls.u2.executable_obj_flags & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD)); + + /* Byte code is executed at the first time. */ + left_value = stack_top_p[-1]; + result = ecma_op_get_iterator (left_value, ECMA_VALUE_ASYNC_ITERATOR, stack_top_p - 1); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (left_value); + left_value = result; + result = ecma_op_iterator_next (left_value, stack_top_p[-1], ECMA_VALUE_UNDEFINED); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + result = ecma_promise_async_await (async_generator_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + async_generator_object_p->u.cls.u2.executable_obj_flags |= ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD; + *VM_GET_EXECUTABLE_ITERATOR (frame_ctx_p) = left_value; + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_AWAIT: + { + if (JERRY_UNLIKELY (!(frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE))) + { + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = --stack_top_p; + + result = opfunc_async_create_and_await (frame_ctx_p, *stack_top_p, 0); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + return result; + } + /* FALLTHRU */ + } + case VM_OC_GENERATOR_AWAIT: + { + ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + + result = ecma_promise_async_await (async_generator_object_p, *(--stack_top_p)); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_EXT_RETURN: + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + + ecma_value_t *stack_bottom_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + while (stack_top_p > stack_bottom_p) + { + ecma_fast_free_value (*(--stack_top_p)); + } + + goto error; + } + case VM_OC_ASYNC_EXIT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + if (!(frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE)) + { + result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED, NULL); + } + else + { + result = *VM_GET_EXECUTABLE_ITERATOR (frame_ctx_p); + *VM_GET_EXECUTABLE_ITERATOR (frame_ctx_p) = ECMA_VALUE_UNDEFINED; + } + + vm_stack_context_type_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]); + + if (context_type == VM_CONTEXT_TRY) + { + JERRY_ASSERT (frame_ctx_p->context_depth == PARSER_TRY_CONTEXT_STACK_ALLOCATION); + left_value = ECMA_VALUE_UNDEFINED; + } + else + { + JERRY_ASSERT (frame_ctx_p->context_depth == PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + left_value = stack_top_p[-2]; + } + + if (context_type == VM_CONTEXT_FINALLY_THROW) + { + ecma_reject_promise (result, left_value); + } + else + { + JERRY_ASSERT (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_FINALLY_RETURN); + ecma_fulfill_promise (result, left_value); + } + + ecma_free_value (left_value); + + frame_ctx_p->context_depth = 0; + frame_ctx_p->call_operation = VM_NO_EXEC_OP; + return result; + } + case VM_OC_STRING_CONCAT: + { + ecma_string_t *left_str_p = ecma_op_to_string (left_value); + + if (JERRY_UNLIKELY (left_str_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + ecma_string_t *right_str_p = ecma_op_to_string (right_value); + + if (JERRY_UNLIKELY (right_str_p == NULL)) + { + ecma_deref_ecma_string (left_str_p); + result = ECMA_VALUE_ERROR; + goto error; + } + + ecma_string_t *result_str_p = ecma_concat_ecma_strings (left_str_p, right_str_p); + ecma_deref_ecma_string (right_str_p); + + *stack_top_p++ = ecma_make_string_value (result_str_p); + goto free_both_values; + } + case VM_OC_GET_TEMPLATE_OBJECT: + { + uint8_t tagged_idx = *byte_code_p++; + ecma_collection_t *collection_p = ecma_compiled_code_get_tagged_template_collection (bytecode_header_p); + JERRY_ASSERT (tagged_idx < collection_p->item_count); + + *stack_top_p++ = ecma_copy_value (collection_p->buffer_p[tagged_idx]); + continue; + } + case VM_OC_PUSH_NEW_TARGET: + { + ecma_object_t *new_target_object_p = JERRY_CONTEXT (current_new_target_p); + if (new_target_object_p == NULL) + { + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + } + else + { + ecma_ref_object (new_target_object_p); + *stack_top_p++ = ecma_make_object_value (new_target_object_p); + } + continue; + } + case VM_OC_REQUIRE_OBJECT_COERCIBLE: + { + if (!ecma_op_require_object_coercible (stack_top_p[-1])) + { + result = ECMA_VALUE_ERROR; + goto error; + } + continue; + } + case VM_OC_ASSIGN_SUPER: + { + result = opfunc_assign_super_reference (&stack_top_p, frame_ctx_p, opcode_data); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + continue; + } + case VM_OC_PUSH_ELISON: + { + *stack_top_p++ = ECMA_VALUE_ARRAY_HOLE; + continue; + } + case VM_OC_APPEND_ARRAY: + { + uint16_t values_length = *byte_code_p++; + stack_top_p -= values_length; + + if (*byte_code_start_p == CBC_EXT_OPCODE) + { + values_length = (uint16_t) (values_length | OPFUNC_HAS_SPREAD_ELEMENT); + } + result = opfunc_append_array (stack_top_p, values_length); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + continue; + } + case VM_OC_IDENT_REFERENCE: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index < ident_end); + + if (literal_index < register_end) + { + *stack_top_p++ = ECMA_VALUE_REGISTER_REF; + *stack_top_p++ = ecma_make_integer_value (literal_index); + *stack_top_p++ = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + } + else + { + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + ecma_object_t *ref_base_lex_env_p; + + result = ecma_op_get_value_lex_env_base (frame_ctx_p->lex_env_p, &ref_base_lex_env_p, name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_ref_object (ref_base_lex_env_p); + ecma_ref_ecma_string (name_p); + *stack_top_p++ = ecma_make_object_value (ref_base_lex_env_p); + *stack_top_p++ = ecma_make_string_value (name_p); + *stack_top_p++ = result; + } + continue; + } + case VM_OC_PROP_GET: + { + result = vm_op_get_value (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_PROP_REFERENCE: + { + /* Forms with reference requires preserving the base and offset. */ + + if (opcode == CBC_PUSH_PROP_REFERENCE) + { + left_value = stack_top_p[-2]; + right_value = stack_top_p[-1]; + } + else if (opcode == CBC_PUSH_PROP_LITERAL_REFERENCE) + { + *stack_top_p++ = left_value; + right_value = left_value; + left_value = stack_top_p[-2]; + } + else + { + JERRY_ASSERT (opcode == CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE + || opcode == CBC_PUSH_PROP_THIS_LITERAL_REFERENCE); + *stack_top_p++ = left_value; + *stack_top_p++ = right_value; + } + /* FALLTHRU */ + } + case VM_OC_PROP_PRE_INCR: + case VM_OC_PROP_PRE_DECR: + case VM_OC_PROP_POST_INCR: + case VM_OC_PROP_POST_DECR: + { + result = vm_op_get_value (left_value, right_value); + + if (opcode < CBC_PRE_INCR) + { + left_value = ECMA_VALUE_UNDEFINED; + right_value = ECMA_VALUE_UNDEFINED; + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + if (opcode < CBC_PRE_INCR) + { + break; + } + + stack_top_p += 2; + left_value = result; + right_value = ECMA_VALUE_UNDEFINED; + /* FALLTHRU */ + } + case VM_OC_PRE_INCR: + case VM_OC_PRE_DECR: + case VM_OC_POST_INCR: + case VM_OC_POST_DECR: + { + uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_PROP_PRE_INCR; + ecma_number_t result_number; + + byte_code_p = byte_code_start_p + 1; + + if (ecma_is_value_integer_number (left_value)) + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + + ecma_integer_value_t int_value = (ecma_integer_value_t) result; + ecma_integer_value_t int_increase = 0; + + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + { + if (int_value > ECMA_INTEGER_NUMBER_MIN_SHIFTED) + { + int_increase = -(1 << ECMA_DIRECT_SHIFT); + } + } + else if (int_value < ECMA_INTEGER_NUMBER_MAX_SHIFTED) + { + int_increase = 1 << ECMA_DIRECT_SHIFT; + } + + if (JERRY_LIKELY (int_increase != 0)) + { + /* Postfix operators require the unmodifed number value. */ + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + { + POST_INCREASE_DECREASE_PUT_RESULT (result); + } + + result = (ecma_value_t) (int_value + int_increase); + break; + } + result_number = (ecma_number_t) ecma_get_integer_from_value (result); + } + else if (ecma_is_value_float_number (left_value)) + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + result_number = ecma_get_number_from_value (result); + } + else + { + result = ecma_op_to_numeric (left_value, &result_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_free_value (left_value); + left_value = ECMA_VALUE_UNDEFINED; + +#if JERRY_BUILTIN_BIGINT + if (JERRY_UNLIKELY (ecma_is_value_bigint (result))) + { + ecma_bigint_unary_operation_type operation_type = ECMA_BIGINT_UNARY_INCREASE; + + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + { + operation_type = ECMA_BIGINT_UNARY_DECREASE; + } + + /* Postfix operators require the unmodifed number value. */ + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + { + POST_INCREASE_DECREASE_PUT_RESULT (result); + + result = ecma_bigint_unary (result, operation_type); + } + else + { + ecma_value_t original_value = result; + result = ecma_bigint_unary (original_value, operation_type); + ecma_free_value (original_value); + } + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + break; + } +#endif /* JERRY_BUILTIN_BIGINT */ + + result = ecma_make_number_value (result_number); + } + + ecma_number_t increase = ECMA_NUMBER_ONE; + + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + { + /* For decrement operators */ + increase = ECMA_NUMBER_MINUS_ONE; + } + + /* Postfix operators require the unmodifed number value. */ + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + { + POST_INCREASE_DECREASE_PUT_RESULT (result); + + result = ecma_make_number_value (result_number + increase); + break; + } + + if (ecma_is_value_integer_number (result)) + { + result = ecma_make_number_value (result_number + increase); + } + else + { + result = ecma_update_float_number (result, result_number + increase); + } + break; + } + case VM_OC_ASSIGN: + { + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + break; + } + case VM_OC_MOV_IDENT: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index < register_end); + JERRY_ASSERT (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))); + + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = left_value; + continue; + } + case VM_OC_ASSIGN_PROP: + { + result = stack_top_p[-1]; + stack_top_p[-1] = left_value; + left_value = ECMA_VALUE_UNDEFINED; + break; + } + case VM_OC_ASSIGN_PROP_THIS: + { + result = stack_top_p[-1]; + stack_top_p[-1] = ecma_copy_value (frame_ctx_p->this_binding); + *stack_top_p++ = left_value; + left_value = ECMA_VALUE_UNDEFINED; + break; + } + case VM_OC_RETURN_FUNCTION_END: + { + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_SCRIPT) + { + result = VM_GET_REGISTER (frame_ctx_p, 0); + VM_GET_REGISTERS (frame_ctx_p)[0] = ECMA_VALUE_UNDEFINED; + } + else + { + result = ECMA_VALUE_UNDEFINED; + } + + goto error; + } + case VM_OC_RETURN: + { + JERRY_ASSERT (opcode == CBC_RETURN || opcode == CBC_RETURN_WITH_LITERAL); + + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + goto error; + } + case VM_OC_THROW: + { + jcontext_raise_exception (left_value); + + result = ECMA_VALUE_ERROR; + left_value = ECMA_VALUE_UNDEFINED; + goto error; + } + case VM_OC_THROW_REFERENCE_ERROR: + { + result = ecma_raise_reference_error (ECMA_ERR_UNDEFINED_REFERENCE); + goto error; + } + case VM_OC_EVAL: + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_DIRECT_EVAL; + JERRY_ASSERT ((*byte_code_p >= CBC_CALL && *byte_code_p <= CBC_CALL2_PROP_BLOCK) + || (*byte_code_p == CBC_EXT_OPCODE && byte_code_p[1] >= CBC_EXT_SPREAD_CALL + && byte_code_p[1] <= CBC_EXT_SPREAD_CALL_PROP_BLOCK)); + continue; + } + case VM_OC_CALL: + { + frame_ctx_p->call_operation = VM_EXEC_CALL; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_NEW: + { + frame_ctx_p->call_operation = VM_EXEC_CONSTRUCT; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_ERROR: + { + JERRY_ASSERT (frame_ctx_p->byte_code_p[1] == CBC_EXT_ERROR); + + result = ECMA_VALUE_ERROR; + goto error; + } + case VM_OC_RESOLVE_BASE_FOR_CALL: + { + ecma_value_t this_value = stack_top_p[-3]; + + if (this_value == ECMA_VALUE_REGISTER_REF) + { + /* Lexical environment cannot be 'this' value. */ + stack_top_p[-2] = ECMA_VALUE_UNDEFINED; + stack_top_p[-3] = ECMA_VALUE_UNDEFINED; + } + else if (vm_get_implicit_this_value (&this_value)) + { + ecma_free_value (stack_top_p[-3]); + stack_top_p[-3] = this_value; + } + + continue; + } + case VM_OC_PROP_DELETE: + { + result = vm_op_delete_prop (left_value, right_value, is_strict); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_DELETE: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + if (literal_index < register_end) + { + *stack_top_p++ = ECMA_VALUE_FALSE; + continue; + } + + result = vm_op_delete_var (literal_start_p[literal_index], frame_ctx_p->lex_env_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + JERRY_ASSERT (ecma_is_value_boolean (result)); + + *stack_top_p++ = result; + continue; + } + case VM_OC_JUMP: + { + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + case VM_OC_BRANCH_IF_STRICT_EQUAL: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); + + if (ecma_op_strict_equality_compare (value, stack_top_p[-1])) + { + byte_code_p = byte_code_start_p + branch_offset; + ecma_free_value (*--stack_top_p); + } + ecma_free_value (value); + continue; + } + case VM_OC_BRANCH_IF_TRUE: + case VM_OC_BRANCH_IF_FALSE: + case VM_OC_BRANCH_IF_LOGICAL_TRUE: + case VM_OC_BRANCH_IF_LOGICAL_FALSE: + { + uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_BRANCH_IF_TRUE; + ecma_value_t value = *(--stack_top_p); + + bool boolean_value = ecma_op_to_boolean (value); + + if (opcode_flags & VM_OC_BRANCH_IF_FALSE_FLAG) + { + boolean_value = !boolean_value; + } + + if (boolean_value) + { + byte_code_p = byte_code_start_p + branch_offset; + if (opcode_flags & VM_OC_LOGICAL_BRANCH_FLAG) + { + /* "Push" the value back to the stack. */ + ++stack_top_p; + continue; + } + } + + ecma_fast_free_value (value); + continue; + } + case VM_OC_POP_REFERENCE: + { + ecma_free_value (stack_top_p[-2]); + ecma_free_value (stack_top_p[-3]); + stack_top_p[-3] = stack_top_p[-1]; + stack_top_p -= 2; + continue; + } + case VM_OC_BRANCH_IF_NULLISH: + { + left_value = stack_top_p[-1]; + + if (!ecma_is_value_null (left_value) && !ecma_is_value_undefined (left_value)) + { + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + --stack_top_p; + continue; + } + case VM_OC_PLUS: + case VM_OC_MINUS: + { + result = opfunc_unary_operation (left_value, VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_PLUS); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_NOT: + { + *stack_top_p++ = ecma_make_boolean_value (!ecma_op_to_boolean (left_value)); + JERRY_ASSERT (ecma_is_value_boolean (stack_top_p[-1])); + goto free_left_value; + } + case VM_OC_BIT_NOT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_is_value_integer_number (left_value)) + { + *stack_top_p++ = (~ECMA_DIRECT_TYPE_MASK) ^ left_value; + goto free_left_value; + } + + result = do_number_bitwise_not (left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_VOID: + { + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + goto free_left_value; + } + case VM_OC_TYPEOF_IDENT: + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + JERRY_ASSERT (literal_index < ident_end); + + if (literal_index < register_end) + { + left_value = ecma_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + } + else + { + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + ecma_object_t *ref_base_lex_env_p; + + result = ecma_op_get_value_lex_env_base (frame_ctx_p->lex_env_p, &ref_base_lex_env_p, name_p); + + if (ref_base_lex_env_p == NULL) + { + jcontext_release_exception (); + result = ECMA_VALUE_UNDEFINED; + } + else if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + left_value = result; + } + /* FALLTHRU */ + } + case VM_OC_TYPEOF: + { + result = opfunc_typeof (left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_left_value; + } + case VM_OC_ADD: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_int32_value ((int32_t) (left_integer + right_integer)); + continue; + } + + if (ecma_is_value_float_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t new_value = + (ecma_get_float_from_value (left_value) + ecma_get_number_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (left_value, new_value); + ecma_free_number (right_value); + continue; + } + + if (ecma_is_value_float_number (right_value) && ecma_is_value_integer_number (left_value)) + { + ecma_number_t new_value = + ((ecma_number_t) ecma_get_integer_from_value (left_value) + ecma_get_float_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (right_value, new_value); + continue; + } + + result = opfunc_addition (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_SUB: + { + JERRY_STATIC_ASSERT (ECMA_INTEGER_NUMBER_MAX * 2 <= INT32_MAX && ECMA_INTEGER_NUMBER_MIN * 2 >= INT32_MIN, + doubled_ecma_numbers_must_fit_into_int32_range); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_int32_value ((int32_t) (left_integer - right_integer)); + continue; + } + + if (ecma_is_value_float_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t new_value = + (ecma_get_float_from_value (left_value) - ecma_get_number_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (left_value, new_value); + ecma_free_number (right_value); + continue; + } + + if (ecma_is_value_float_number (right_value) && ecma_is_value_integer_number (left_value)) + { + ecma_number_t new_value = + ((ecma_number_t) ecma_get_integer_from_value (left_value) - ecma_get_float_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (right_value, new_value); + continue; + } + + result = do_number_arithmetic (NUMBER_ARITHMETIC_SUBTRACTION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_MUL: + { + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + JERRY_STATIC_ASSERT (ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX <= ECMA_INTEGER_NUMBER_MAX + && -(ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX) >= ECMA_INTEGER_NUMBER_MIN, + square_of_integer_multiply_max_must_fit_into_integer_value_range); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + + if (-ECMA_INTEGER_MULTIPLY_MAX <= left_integer && left_integer <= ECMA_INTEGER_MULTIPLY_MAX + && -ECMA_INTEGER_MULTIPLY_MAX <= right_integer && right_integer <= ECMA_INTEGER_MULTIPLY_MAX + && left_integer != 0 && right_integer != 0) + { + *stack_top_p++ = ecma_integer_multiply (left_integer, right_integer); + continue; + } + + ecma_number_t multiply = (ecma_number_t) left_integer * (ecma_number_t) right_integer; + *stack_top_p++ = ecma_make_number_value (multiply); + continue; + } + + if (ecma_is_value_float_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t new_value = + (ecma_get_float_from_value (left_value) * ecma_get_number_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (left_value, new_value); + ecma_free_number (right_value); + continue; + } + + if (ecma_is_value_float_number (right_value) && ecma_is_value_integer_number (left_value)) + { + ecma_number_t new_value = + ((ecma_number_t) ecma_get_integer_from_value (left_value) * ecma_get_float_from_value (right_value)); + + *stack_top_p++ = ecma_update_float_number (right_value, new_value); + continue; + } + + result = do_number_arithmetic (NUMBER_ARITHMETIC_MULTIPLICATION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_DIV: + { + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + result = do_number_arithmetic (NUMBER_ARITHMETIC_DIVISION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_MOD: + { + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + + if (right_integer != 0) + { + ecma_integer_value_t mod_result = left_integer % right_integer; + + if (mod_result != 0 || left_integer >= 0) + { + *stack_top_p++ = ecma_make_integer_value (mod_result); + continue; + } + } + } + + result = do_number_arithmetic (NUMBER_ARITHMETIC_REMAINDER, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_EXP: + { + result = do_number_arithmetic (NUMBER_ARITHMETIC_EXPONENTIATION, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_EQUAL: + { + result = opfunc_equality (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_NOT_EQUAL: + { + result = opfunc_equality (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = ecma_invert_boolean_value (result); + goto free_both_values; + } + case VM_OC_STRICT_EQUAL: + { + bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + + result = ecma_make_boolean_value (is_equal); + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_STRICT_NOT_EQUAL: + { + bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + + result = ecma_make_boolean_value (!is_equal); + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BIT_OR: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + *stack_top_p++ = left_value | right_value; + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_LOGIC_OR, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BIT_XOR: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + *stack_top_p++ = left_value ^ right_value; + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_LOGIC_XOR, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BIT_AND: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + *stack_top_p++ = left_value & right_value; + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_LOGIC_AND, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_LEFT_SHIFT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + + *stack_top_p++ = ecma_make_int32_value ((int32_t) ((uint32_t) left_integer << (right_integer & 0x1f))); + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_SHIFT_LEFT, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_RIGHT_SHIFT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_integer_value (left_integer >> (right_integer & 0x1f)); + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_SHIFT_RIGHT, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_UNS_RIGHT_SHIFT: + { + JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1)), + direct_type_mask_must_fill_all_bits_before_the_value_starts); + + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + uint32_t left_uint32 = (uint32_t) ecma_get_integer_from_value (left_value); + ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value); + *stack_top_p++ = ecma_make_uint32_value (left_uint32 >> (right_integer & 0x1f)); + continue; + } + + result = do_number_bitwise_logic (NUMBER_BITWISE_SHIFT_URIGHT, left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_LESS: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + bool is_less = (ecma_integer_value_t) left_value < (ecma_integer_value_t) right_value; +#if !JERRY_VM_HALT + /* This is a lookahead to the next opcode to improve performance. + * If it is CBC_BRANCH_IF_TRUE_BACKWARD, execute it. */ + if (*byte_code_p <= CBC_BRANCH_IF_TRUE_BACKWARD_3 && *byte_code_p >= CBC_BRANCH_IF_TRUE_BACKWARD) + { + byte_code_start_p = byte_code_p++; + branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (*byte_code_start_p); + JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3); + + if (is_less) + { + branch_offset = *(byte_code_p++); + + if (JERRY_UNLIKELY (branch_offset_length != 1)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + if (JERRY_UNLIKELY (branch_offset_length == 3)) + { + branch_offset <<= 8; + branch_offset |= *(byte_code_p++); + } + } + + /* Note: The opcode is a backward branch. */ + byte_code_p = byte_code_start_p - branch_offset; + } + else + { + byte_code_p += branch_offset_length; + } + + continue; + } +#endif /* !JERRY_VM_HALT */ + *stack_top_p++ = ecma_make_boolean_value (is_less); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number < right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, true, false); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_GREATER: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; + ecma_integer_value_t right_integer = (ecma_integer_value_t) right_value; + + *stack_top_p++ = ecma_make_boolean_value (left_integer > right_integer); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number > right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, false, false); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_LESS_EQUAL: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; + ecma_integer_value_t right_integer = (ecma_integer_value_t) right_value; + + *stack_top_p++ = ecma_make_boolean_value (left_integer <= right_integer); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number <= right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, false, true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_GREATER_EQUAL: + { + if (ecma_are_values_integer_numbers (left_value, right_value)) + { + ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; + ecma_integer_value_t right_integer = (ecma_integer_value_t) right_value; + + *stack_top_p++ = ecma_make_boolean_value (left_integer >= right_integer); + continue; + } + + if (ecma_is_value_number (left_value) && ecma_is_value_number (right_value)) + { + ecma_number_t left_number = ecma_get_number_from_value (left_value); + ecma_number_t right_number = ecma_get_number_from_value (right_value); + + *stack_top_p++ = ecma_make_boolean_value (left_number >= right_number); + goto free_both_values; + } + + result = opfunc_relation (left_value, right_value, true, true); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_IN: + { + result = opfunc_in (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_INSTANCEOF: + { + result = opfunc_instanceof (left_value, right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + goto free_both_values; + } + case VM_OC_BLOCK_CREATE_CONTEXT: + { + ecma_value_t *stack_context_top_p; + stack_context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + JERRY_ASSERT (stack_context_top_p == stack_top_p || stack_context_top_p == stack_top_p - 1); + + if (byte_code_start_p[0] != CBC_EXT_OPCODE) + { + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + if (stack_context_top_p != stack_top_p) + { + /* Preserve the value of switch statement. */ + stack_context_top_p[1] = stack_context_top_p[0]; + } + + stack_context_top_p[0] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_BLOCK, branch_offset); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_BLOCK_CONTEXT_STACK_ALLOCATION; + } + else + { + JERRY_ASSERT (byte_code_start_p[1] == CBC_EXT_TRY_CREATE_ENV); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_TRY + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_CATCH + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_THROW + || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); + + JERRY_ASSERT (!(stack_context_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)); + + stack_context_top_p[-1] |= VM_CONTEXT_HAS_LEX_ENV; + } + + frame_ctx_p->lex_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); + frame_ctx_p->lex_env_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + + continue; + } + case VM_OC_WITH: + { + ecma_value_t value = *(--stack_top_p); + ecma_object_t *object_p; + ecma_object_t *with_env_p; + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + result = ecma_op_to_object (value); + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + object_p = ecma_get_object_from_value (result); + + with_env_p = ecma_create_object_lex_env (frame_ctx_p->lex_env_p, object_p); + ecma_deref_object (object_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_WITH_CONTEXT_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_WITH, branch_offset); + + with_env_p->type_flags_refs |= ECMA_OBJECT_FLAG_BLOCK; + frame_ctx_p->lex_env_p = with_env_p; + continue; + } + case VM_OC_FOR_IN_INIT: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_value_t expr_obj_value = ECMA_VALUE_UNDEFINED; + ecma_collection_t *prop_names_p = opfunc_for_in (value, &expr_obj_value); + ecma_free_value (value); + + if (prop_names_p == NULL) + { + if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (expr_obj_value))) + { + result = expr_obj_value; + goto error; + } + + /* The collection is already released */ + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_IN, branch_offset); + ECMA_SET_INTERNAL_VALUE_ANY_POINTER (stack_top_p[-2], prop_names_p); + stack_top_p[-3] = 0; + stack_top_p[-4] = expr_obj_value; + + if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT) + { + /* No need to duplicate the first context. */ + byte_code_p += 2; + } + + continue; + } + case VM_OC_FOR_IN_GET_NEXT: + { + ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + ecma_collection_t *collection_p; + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_top_p[-2]); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_IN); + + uint32_t index = context_top_p[-3]; + ecma_value_t *buffer_p = collection_p->buffer_p; + + *stack_top_p++ = buffer_p[index]; + context_top_p[-3]++; + continue; + } + case VM_OC_FOR_IN_HAS_NEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_collection_t *collection_p; + collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, stack_top_p[-2]); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_IN); + + ecma_value_t *buffer_p = collection_p->buffer_p; + ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[-4]); + uint32_t index = stack_top_p[-3]; + + while (index < collection_p->item_count) + { + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[index]); + + result = ecma_op_object_has_property (object_p, prop_name_p); + + if (ECMA_IS_VALUE_ERROR (result)) + { + stack_top_p[-3] = index; + goto error; + } + + if (JERRY_LIKELY (ecma_is_value_true (result))) + { + byte_code_p = byte_code_start_p + branch_offset; + break; + } + + ecma_deref_ecma_string (prop_name_p); + index++; + } + + if (index == collection_p->item_count) + { + ecma_deref_object (object_p); + ecma_collection_destroy (collection_p); + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION; + } + else + { + stack_top_p[-3] = index; + } + continue; + } + case VM_OC_FOR_OF_INIT: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_value_t next_method; + ecma_value_t iterator = ecma_op_get_iterator (value, ECMA_VALUE_SYNC_ITERATOR, &next_method); + + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (iterator)) + { + result = iterator; + goto error; + } + + result = ecma_op_iterator_step (iterator, next_method); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (iterator); + ecma_free_value (next_method); + goto error; + } + + if (ecma_is_value_false (result)) + { + ecma_free_value (iterator); + ecma_free_value (next_method); + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + + ecma_value_t next_value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + result = next_value; + ecma_free_value (iterator); + ecma_free_value (next_method); + goto error; + } + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION; + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_OF, branch_offset) | VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = next_value; + stack_top_p[-3] = iterator; + stack_top_p[-4] = next_method; + + if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT) + { + /* No need to duplicate the first context. */ + byte_code_p += 2; + } + continue; + } + case VM_OC_FOR_OF_GET_NEXT: + { + ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_OF + || VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + JERRY_ASSERT (context_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); + + *stack_top_p++ = context_top_p[-2]; + context_top_p[-2] = ECMA_VALUE_UNDEFINED; + continue; + } + case VM_OC_FOR_OF_HAS_NEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_OF); + JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); + + stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = ecma_op_iterator_step (stack_top_p[-3], stack_top_p[-4]); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + if (ecma_is_value_false (result)) + { + ecma_free_value (stack_top_p[-2]); + ecma_free_value (stack_top_p[-3]); + ecma_free_value (stack_top_p[-4]); + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION; + continue; + } + + ecma_value_t next_value = ecma_op_iterator_value (result); + ecma_free_value (result); + + if (ECMA_IS_VALUE_ERROR (next_value)) + { + result = next_value; + goto error; + } + + JERRY_ASSERT (stack_top_p[-2] == ECMA_VALUE_UNDEFINED); + stack_top_p[-1] |= VM_CONTEXT_CLOSE_ITERATOR; + stack_top_p[-2] = next_value; + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + case VM_OC_FOR_AWAIT_OF_INIT: + { + ecma_value_t value = *(--stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + ecma_value_t next_method; + result = ecma_op_get_iterator (value, ECMA_VALUE_ASYNC_ITERATOR, &next_method); + + ecma_free_value (value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_value_t iterator = result; + result = ecma_op_iterator_next (result, next_method, ECMA_VALUE_EMPTY); + + if (ECMA_IS_VALUE_ERROR (result)) + { + ecma_free_value (iterator); + ecma_free_value (next_method); + goto error; + } + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION; + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_AWAIT_OF, branch_offset); + stack_top_p[-2] = ECMA_VALUE_UNDEFINED; + stack_top_p[-3] = iterator; + stack_top_p[-4] = next_method; + + if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT) + { + /* No need to duplicate the first context. */ + byte_code_p += 2; + } + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_p; + frame_ctx_p->stack_top_p = stack_top_p; + + uint16_t extra_flags = + (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD | (ECMA_AWAIT_FOR_NEXT << ECMA_AWAIT_STATE_SHIFT)); + + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR + || (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE)) + { + ecma_extended_object_t *executable_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + result = ecma_promise_async_await (executable_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + executable_object_p->u.cls.u2.executable_obj_flags |= extra_flags; + return ECMA_VALUE_UNDEFINED; + } + + result = opfunc_async_create_and_await (frame_ctx_p, result, extra_flags); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + return result; + } + case VM_OC_FOR_AWAIT_OF_HAS_NEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); + JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); + + stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR; + result = ecma_op_iterator_next (stack_top_p[-3], stack_top_p[-4], ECMA_VALUE_EMPTY); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + ecma_extended_object_t *executable_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); + result = ecma_promise_async_await (executable_object_p, result); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + uint16_t extra_flags = + (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD | (ECMA_AWAIT_FOR_NEXT << ECMA_AWAIT_STATE_SHIFT)); + executable_object_p->u.cls.u2.executable_obj_flags |= extra_flags; + + frame_ctx_p->call_operation = VM_EXEC_RETURN; + frame_ctx_p->byte_code_p = byte_code_start_p + branch_offset; + frame_ctx_p->stack_top_p = stack_top_p; + return ECMA_VALUE_UNDEFINED; + } + case VM_OC_TRY: + { + /* Try opcode simply creates the try context. */ + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); + stack_top_p += PARSER_TRY_CONTEXT_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_TRY, branch_offset); + continue; + } + case VM_OC_CATCH: + { + /* Catches are ignored and turned to jumps. */ + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY); + + byte_code_p = byte_code_start_p + branch_offset; + continue; + } + case VM_OC_FINALLY: + { + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY + || VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH); + + if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION); + stack_top_p += PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION; + + stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FINALLY_JUMP, branch_offset); + stack_top_p[-2] = (ecma_value_t) branch_offset; + continue; + } + case VM_OC_CONTEXT_END: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)); + + ecma_value_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]); + + if (!VM_CONTEXT_IS_FINALLY (context_type)) + { + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + continue; + } + + if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV) + { + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + ecma_deref_object (lex_env_p); + } + + VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); + stack_top_p -= PARSER_FINALLY_CONTEXT_STACK_ALLOCATION; + + if (context_type == VM_CONTEXT_FINALLY_RETURN) + { + result = *stack_top_p; + goto error; + } + + if (context_type == VM_CONTEXT_FINALLY_THROW) + { + jcontext_raise_exception (*stack_top_p); +#if JERRY_VM_THROW + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_THROWN; +#endif /* JERRY_VM_THROW */ + result = ECMA_VALUE_ERROR; + goto error; + } + + JERRY_ASSERT (context_type == VM_CONTEXT_FINALLY_JUMP); + + uint32_t jump_target = *stack_top_p; + + vm_stack_found_type type = + vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_JUMP, jump_target); + stack_top_p = frame_ctx_p->stack_top_p; + switch (type) + { + case VM_CONTEXT_FOUND_FINALLY: + { + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = jump_target; + break; + } + case VM_CONTEXT_FOUND_ERROR: + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + result = ECMA_VALUE_ERROR; + goto error; + } + case VM_CONTEXT_FOUND_AWAIT: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = jump_target; + return ECMA_VALUE_UNDEFINED; + } + default: + { + byte_code_p = frame_ctx_p->byte_code_start_p + jump_target; + break; + } + } + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + continue; + } + case VM_OC_JUMP_AND_EXIT_CONTEXT: + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (!jcontext_has_pending_exception ()); + + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); + + vm_stack_found_type type = + vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_JUMP, (uint32_t) branch_offset); + stack_top_p = frame_ctx_p->stack_top_p; + switch (type) + { + case VM_CONTEXT_FOUND_FINALLY: + { + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = (uint32_t) branch_offset; + break; + } + case VM_CONTEXT_FOUND_ERROR: + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + result = ECMA_VALUE_ERROR; + goto error; + } + case VM_CONTEXT_FOUND_AWAIT: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP); + stack_top_p[-2] = (uint32_t) branch_offset; + return ECMA_VALUE_UNDEFINED; + } + default: + { + byte_code_p = frame_ctx_p->byte_code_start_p + branch_offset; + break; + } + } + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + continue; + } +#if JERRY_MODULE_SYSTEM + case VM_OC_MODULE_IMPORT: + { + left_value = *(--stack_top_p); + + ecma_value_t user_value = ECMA_VALUE_UNDEFINED; + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + +#if JERRY_SNAPSHOT_EXEC + if (JERRY_UNLIKELY (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE) + { + user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); + } +#if JERRY_SNAPSHOT_EXEC + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + result = ecma_module_import (left_value, user_value); + ecma_free_value (left_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } + + *stack_top_p++ = result; + continue; + } + case VM_OC_MODULE_IMPORT_META: + { + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_IMPORT_META); + + ecma_value_t import_meta = CBC_SCRIPT_GET_IMPORT_META (script_p, script_p->refs_and_type); + ecma_object_t *import_meta_object_p = ecma_get_object_from_value (import_meta); + + if (ecma_get_object_type (import_meta_object_p) != ECMA_OBJECT_TYPE_GENERAL) + { + JERRY_ASSERT (ecma_object_class_is (import_meta_object_p, ECMA_OBJECT_CLASS_MODULE)); + + ecma_value_t module = import_meta; + import_meta_object_p = ecma_create_object (NULL, 0, ECMA_OBJECT_TYPE_GENERAL); + import_meta = ecma_make_object_value (import_meta_object_p); + + if (JERRY_CONTEXT (module_import_meta_callback_p) != NULL) + { + void *user_p = JERRY_CONTEXT (module_import_meta_callback_user_p); + JERRY_CONTEXT (module_import_meta_callback_p) (module, import_meta, user_p); + } + + CBC_SCRIPT_GET_IMPORT_META (script_p, script_p->refs_and_type) = import_meta; + } + else + { + ecma_ref_object (import_meta_object_p); + } + + *stack_top_p++ = import_meta; + continue; + } +#endif /* JERRY_MODULE_SYSTEM */ + case VM_OC_NONE: + default: + { + JERRY_ASSERT (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_NONE); + + jerry_fatal (JERRY_FATAL_DISABLED_BYTE_CODE); + } + } + + JERRY_ASSERT (VM_OC_HAS_PUT_RESULT (opcode_data)); + + if (opcode_data & VM_OC_PUT_IDENT) + { + uint16_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + if (literal_index < register_end) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = result; + + if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)) + { + result = ecma_fast_copy_value (result); + } + } + else + { + ecma_string_t *var_name_str_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + ecma_value_t put_value_result = + ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p, var_name_str_p, is_strict, result); + + if (ECMA_IS_VALUE_ERROR (put_value_result)) + { + ecma_free_value (result); + result = put_value_result; + goto error; + } + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (result); + } + } + } + else if (opcode_data & VM_OC_PUT_REFERENCE) + { + ecma_value_t property = *(--stack_top_p); + ecma_value_t base = *(--stack_top_p); + + if (base == ECMA_VALUE_REGISTER_REF) + { + property = (ecma_value_t) ecma_get_integer_from_value (property); + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, property)); + VM_GET_REGISTER (frame_ctx_p, property) = result; + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + goto free_both_values; + } + result = ecma_fast_copy_value (result); + } + else + { + ecma_value_t set_value_result = vm_op_set_value (base, property, result, is_strict); + + if (ECMA_IS_VALUE_ERROR (set_value_result)) + { + ecma_free_value (result); + result = set_value_result; + goto error; + } + + if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + { + ecma_fast_free_value (result); + goto free_both_values; + } + } + } + + if (opcode_data & VM_OC_PUT_STACK) + { + *stack_top_p++ = result; + } + else if (opcode_data & VM_OC_PUT_BLOCK) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = result; + } + +free_both_values: + ecma_fast_free_value (right_value); +free_left_value: + ecma_fast_free_value (left_value); + } + +error: + ecma_fast_free_value (left_value); + ecma_fast_free_value (right_value); + + if (ECMA_IS_VALUE_ERROR (result)) + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + ecma_value_t *stack_bottom_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + + while (stack_top_p > stack_bottom_p) + { + ecma_value_t stack_item = *(--stack_top_p); + if (stack_item == ECMA_VALUE_RELEASE_LEX_ENV) + { + opfunc_pop_lexical_environment (frame_ctx_p); + continue; + } + + ecma_fast_free_value (stack_item); + } + +#if JERRY_VM_THROW + if (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_ERROR_THROWN)) + { + JERRY_CONTEXT (status_flags) |= ECMA_STATUS_ERROR_THROWN; + + jerry_throw_cb_t vm_throw_callback_p = JERRY_CONTEXT (vm_throw_callback_p); + + if (vm_throw_callback_p != NULL) + { + vm_throw_callback_p (JERRY_CONTEXT (error_value), JERRY_CONTEXT (vm_throw_callback_user_p)); + } + } +#endif /* JERRY_VM_THROW */ + } + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + if (frame_ctx_p->context_depth == 0) + { + /* In most cases there is no context. */ + frame_ctx_p->call_operation = VM_NO_EXEC_OP; + return result; + } + + if (!ECMA_IS_VALUE_ERROR (result)) + { + switch (vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_RETURN, 0)) + { + case VM_CONTEXT_FOUND_FINALLY: + { + stack_top_p = frame_ctx_p->stack_top_p; + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + stack_top_p[-2] = result; + continue; + } + case VM_CONTEXT_FOUND_ERROR: + { + JERRY_ASSERT (jcontext_has_pending_exception ()); + + ecma_free_value (result); + stack_top_p = frame_ctx_p->stack_top_p; + result = ECMA_VALUE_ERROR; + break; + } + case VM_CONTEXT_FOUND_AWAIT: + { + stack_top_p = frame_ctx_p->stack_top_p; + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); + stack_top_p[-2] = result; + return ECMA_VALUE_UNDEFINED; + } + default: + { + goto finish; + } + } + } + + JERRY_ASSERT (jcontext_has_pending_exception ()); + + if (!jcontext_has_pending_abort ()) + { + switch (vm_stack_find_finally (frame_ctx_p, stack_top_p, VM_CONTEXT_FINALLY_THROW, 0)) + { + case VM_CONTEXT_FOUND_FINALLY: + { + stack_top_p = frame_ctx_p->stack_top_p; + byte_code_p = frame_ctx_p->byte_code_p; + + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)); + + result = jcontext_take_exception (); + + if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW) + { + stack_top_p[-2] = result; + continue; + } + + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH); + + *stack_top_p++ = result; + continue; + } + case VM_CONTEXT_FOUND_AWAIT: + { + JERRY_ASSERT (VM_GET_CONTEXT_TYPE (frame_ctx_p->stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW); + return ECMA_VALUE_UNDEFINED; + } + default: + { + break; + } + } + } + else + { + do + { + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); + + stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); + } while (frame_ctx_p->context_depth > 0); + } + +finish: + frame_ctx_p->call_operation = VM_NO_EXEC_OP; + return result; + } +} /* vm_loop */ + +#if JERRY_MODULE_SYSTEM + +/** + * Create and initialize module scope with all data properties + * + * @return ECMA_VALUE_EMPTY on success, + * ECMA_VALUE_ERROR on failure + */ +ecma_value_t +vm_init_module_scope (ecma_module_t *module_p) /**< module without scope */ +{ + ecma_object_t *global_object_p; +#if JERRY_BUILTIN_REALMS + global_object_p = (ecma_object_t *) ecma_op_function_get_realm (module_p->u.compiled_code_p); +#else /* !JERRY_BUILTIN_REALMS */ + global_object_p = ecma_builtin_get_global (); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *scope_p = ecma_create_lex_env_class (ecma_get_global_environment (global_object_p), + sizeof (ecma_lexical_environment_class_t)); + const ecma_compiled_code_t *compiled_code_p = module_p->u.compiled_code_p; + ecma_value_t *literal_start_p; + uint8_t *byte_code_p; + uint16_t encoding_limit; + uint16_t encoding_delta; + + ((ecma_lexical_environment_class_t *) scope_p)->object_p = (ecma_object_t *) module_p; + ((ecma_lexical_environment_class_t *) scope_p)->type = ECMA_LEX_ENV_CLASS_TYPE_MODULE; + + module_p->scope_p = scope_p; + ecma_deref_object (scope_p); + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + + literal_start_p = (ecma_value_t *) (args_p + 1); + literal_start_p -= args_p->register_end; + byte_code_p = (uint8_t *) (literal_start_p + args_p->literal_end); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + + literal_start_p = (ecma_value_t *) (args_p + 1); + literal_start_p -= args_p->register_end; + byte_code_p = (uint8_t *) (literal_start_p + args_p->literal_end); + } + + /* Prepare for byte code execution. */ + if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + JERRY_ASSERT (*byte_code_p >= CBC_JUMP_FORWARD && *byte_code_p <= CBC_JUMP_FORWARD_3); + + byte_code_p += 1 + CBC_BRANCH_OFFSET_LENGTH (*byte_code_p); + + while (true) + { + uint8_t opcode = *byte_code_p++; + + switch (opcode) + { + case CBC_CREATE_VAR: + case CBC_CREATE_LET: + case CBC_CREATE_CONST: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_find_named_property (scope_p, name_p) == NULL); + + uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; + + if (opcode == CBC_CREATE_LET) + { + prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE; + } + else if (opcode == CBC_CREATE_CONST) + { + prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE; + } + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (scope_p, name_p, prop_attributes, NULL); + + if (opcode != CBC_CREATE_VAR) + { + property_value_p->value = ECMA_VALUE_UNINITIALIZED; + } + break; + } + case CBC_INIT_ARG_OR_FUNC: + { + uint32_t literal_index; + + READ_LITERAL_INDEX (literal_index); + + ecma_compiled_code_t *function_bytecode_p; +#if JERRY_SNAPSHOT_EXEC + if (JERRY_LIKELY (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + { +#endif /* JERRY_SNAPSHOT_EXEC */ + function_bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, literal_start_p[literal_index]); +#if JERRY_SNAPSHOT_EXEC + } + else + { + uint8_t *byte_p = ((uint8_t *) compiled_code_p) + literal_start_p[literal_index]; + function_bytecode_p = (ecma_compiled_code_t *) byte_p; + } +#endif /* JERRY_SNAPSHOT_EXEC */ + + JERRY_ASSERT (CBC_IS_FUNCTION (function_bytecode_p->status_flags)); + + ecma_object_t *function_obj_p; + + if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (function_bytecode_p->status_flags))) + { + function_obj_p = ecma_op_create_arrow_function_object (scope_p, function_bytecode_p, ECMA_VALUE_UNDEFINED); + } + else + { + function_obj_p = ecma_op_create_any_function_object (scope_p, function_bytecode_p); + } + + READ_LITERAL_INDEX (literal_index); + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + + JERRY_ASSERT (ecma_find_named_property (scope_p, name_p) == NULL); + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (scope_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + + JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED); + property_value_p->value = ecma_make_object_value (function_obj_p); + ecma_deref_object (function_obj_p); + break; + } + default: + { + JERRY_ASSERT (opcode == CBC_RETURN_FUNCTION_END); + return ECMA_VALUE_EMPTY; + } + } + } +} /* vm_init_module_scope */ + +#endif /* JERRY_MODULE_SYSTEM */ + +#undef READ_LITERAL +#undef READ_LITERAL_INDEX + +JERRY_STATIC_ASSERT (((int)VM_FRAME_CTX_SHARED_DIRECT_EVAL == (int)VM_FRAME_CTX_DIRECT_EVAL), + vm_frame_ctx_shared_direct_eval_must_be_equal_to_frame_ctx_direct_eval); + +JERRY_STATIC_ASSERT (((int)CBC_CODE_FLAGS_STRICT_MODE == (int)VM_FRAME_CTX_IS_STRICT), + cbc_code_flags_strict_mode_must_be_equal_to_vm_frame_ctx_is_strict); + +/** + * Initialize code block execution + * + * @return ECMA_VALUE_ERROR - if the initialization fails + * ECMA_VALUE_EMPTY - otherwise + */ +static void JERRY_ATTR_NOINLINE +vm_init_exec (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p; + const ecma_compiled_code_t *bytecode_header_p = shared_p->bytecode_header_p; + + frame_ctx_p->prev_context_p = JERRY_CONTEXT (vm_top_context_p); + frame_ctx_p->context_depth = 0; + frame_ctx_p->status_flags = (uint8_t) ((shared_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL) + | (bytecode_header_p->status_flags & VM_FRAME_CTX_IS_STRICT)); + + uint16_t argument_end, register_end; + ecma_value_t *literal_p; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + + argument_end = args_p->argument_end; + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + frame_ctx_p->literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + + argument_end = args_p->argument_end; + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + frame_ctx_p->literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + + frame_ctx_p->byte_code_p = (uint8_t *) literal_p; + frame_ctx_p->byte_code_start_p = (uint8_t *) literal_p; + frame_ctx_p->stack_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end; + + uint32_t arg_list_len = 0; + + if (argument_end > 0) + { + JERRY_ASSERT (shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); + + const ecma_value_t *arg_list_p = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_p; + arg_list_len = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_len; + + if (arg_list_len > argument_end) + { + arg_list_len = argument_end; + } + + for (uint32_t i = 0; i < arg_list_len; i++) + { + VM_GET_REGISTER (frame_ctx_p, i) = ecma_fast_copy_value (arg_list_p[i]); + } + } + + /* The arg_list_len contains the end of the copied arguments. + * Fill everything else with undefined. */ + if (register_end > arg_list_len) + { + ecma_value_t *stack_p = VM_GET_REGISTERS (frame_ctx_p) + arg_list_len; + + for (uint32_t i = arg_list_len; i < register_end; i++) + { + *stack_p++ = ECMA_VALUE_UNDEFINED; + } + } + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; + JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p; +} /* vm_init_exec */ + +/** + * Resume execution of a code block. + * + * @return ecma value + */ +ecma_value_t JERRY_ATTR_NOINLINE +vm_execute (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + while (true) + { + ecma_value_t completion_value = vm_loop (frame_ctx_p); + + switch (frame_ctx_p->call_operation) + { + case VM_EXEC_CALL: + { + opfunc_call (frame_ctx_p); + break; + } + case VM_EXEC_SUPER_CALL: + { + vm_super_call (frame_ctx_p); + break; + } + case VM_EXEC_SPREAD_OP: + { + vm_spread_operation (frame_ctx_p); + break; + } + case VM_EXEC_RETURN: + { + return completion_value; + } + case VM_EXEC_CONSTRUCT: + { + opfunc_construct (frame_ctx_p); + break; + } + default: + { + JERRY_ASSERT (frame_ctx_p->call_operation == VM_NO_EXEC_OP); + + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; + uint32_t register_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + register_end = ((cbc_uint16_arguments_t *) bytecode_header_p)->register_end; + } + else + { + register_end = ((cbc_uint8_arguments_t *) bytecode_header_p)->register_end; + } + + /* Free arguments and registers */ + ecma_value_t *registers_p = VM_GET_REGISTERS (frame_ctx_p); + for (uint32_t i = 0; i < register_end; i++) + { + ecma_fast_free_value (registers_p[i]); + } + JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p->prev_context_p; + return completion_value; + } + } + } +} /* vm_execute */ + +/** + * Run the code. + * + * @return ecma value + */ +ecma_value_t +vm_run (vm_frame_ctx_shared_t *shared_p, /**< shared data */ + ecma_value_t this_binding_value, /**< value of 'ThisBinding' */ + ecma_object_t *lex_env_p) /**< lexical environment to use */ +{ + const ecma_compiled_code_t *bytecode_header_p = shared_p->bytecode_header_p; + vm_frame_ctx_t *frame_ctx_p; + size_t frame_size; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + frame_size = (size_t) (args_p->register_end + args_p->stack_limit); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + frame_size = (size_t) (args_p->register_end + args_p->stack_limit); + } + + JERRY_VLA (ecma_value_t, stack, frame_size + (sizeof (vm_frame_ctx_t) / sizeof (ecma_value_t))); + + frame_ctx_p = (vm_frame_ctx_t *) stack; + + frame_ctx_p->shared_p = shared_p; + frame_ctx_p->lex_env_p = lex_env_p; + frame_ctx_p->this_binding = this_binding_value; + + vm_init_exec (frame_ctx_p); + return vm_execute (frame_ctx_p); +} /* vm_run */ + +/** + * @} + * @} + */ diff --git a/src/loaders/lottie/jerryscript/jerry-core/vm/vm.h b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.h new file mode 100644 index 00000000..5384b071 --- /dev/null +++ b/src/loaders/lottie/jerryscript/jerry-core/vm/vm.h @@ -0,0 +1,426 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VM_H +#define VM_H + +#include "ecma-globals.h" +#include "ecma-module.h" + +#include "jrt.h" +#include "vm-defines.h" + +/** \addtogroup vm Virtual machine + * @{ + * + * \addtogroup vm_executor Executor + * @{ + */ + +/** + * Each CBC opcode is transformed to three vm opcodes: + * + * - first opcode is a "get arguments" opcode which specifies + * the type (register, literal, stack, etc.) and number + * (from 0 to 2) of input arguments + * - second opcode is a "group" opcode which specifies + * the actual operation (add, increment, call, etc.) + * - third opcode is a "put result" opcode which specifies + * the destination where the result is stored (register, + * stack, etc.) + */ + +/** + * If VM_OC_GET_ARGS_INDEX(opcode) == VM_OC_GET_BRANCH, + * this flag signals that the branch is a backward branch. + */ +#define VM_OC_BACKWARD_BRANCH (1 << 15) + +/** + * Position of "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_SHIFT 8 + +/** + * Mask of "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_MASK 0x7 + +/** + * Generate the binary representation of a "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_CREATE_INDEX(V) (((V) &VM_OC_GET_ARGS_MASK) << VM_OC_GET_ARGS_SHIFT) + +/** + * Extract the "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_INDEX(O) ((O) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT)) + +/** + * Checks whether the result is stored somewhere. + */ +#define VM_OC_HAS_GET_ARGS(V) ((V) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT)) + +/** + * Argument getters that are part of the opcodes. + */ +typedef enum +{ + VM_OC_GET_NONE = VM_OC_GET_ARGS_CREATE_INDEX (0), /**< do nothing */ + VM_OC_GET_BRANCH = VM_OC_GET_ARGS_CREATE_INDEX (1), /**< branch argument */ + VM_OC_GET_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop one element from the stack */ + VM_OC_GET_STACK_STACK = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< pop two elements from the stack */ + + VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve literal */ + VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< resolve two literals */ + VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (6), /**< pop one element from the stack + * and resolve a literal */ + VM_OC_GET_THIS_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (7), /**< get this and resolve a literal */ +} vm_oc_get_types; + +/** + * Mask of "group" opcode. + */ +#define VM_OC_GROUP_MASK 0xff + +/** + * Extract the "group" opcode. + */ +#define VM_OC_GROUP_GET_INDEX(O) ((O) &VM_OC_GROUP_MASK) + +/** + * Opcodes. + */ +typedef enum +{ + VM_OC_POP, /**< pop from stack */ + VM_OC_POP_BLOCK, /**< pop block */ + VM_OC_PUSH, /**< push one literal */ + VM_OC_PUSH_TWO, /**< push two literals */ + VM_OC_PUSH_THREE, /**< push three literals */ + VM_OC_PUSH_UNDEFINED, /**< push undefined value */ + VM_OC_PUSH_TRUE, /**< push true value */ + VM_OC_PUSH_FALSE, /**< push false value */ + VM_OC_PUSH_NULL, /**< push null value */ + VM_OC_PUSH_THIS, /**< push this */ + VM_OC_PUSH_0, /**< push number zero */ + VM_OC_PUSH_POS_BYTE, /**< push number between 1 and 256 */ + VM_OC_PUSH_NEG_BYTE, /**< push number between -1 and -256 */ + VM_OC_PUSH_LIT_0, /**< push literal and number zero */ + VM_OC_PUSH_LIT_POS_BYTE, /**< push literal and number between 1 and 256 */ + VM_OC_PUSH_LIT_NEG_BYTE, /**< push literal and number between -1 and -256 */ + VM_OC_PUSH_OBJECT, /**< push object */ + VM_OC_PUSH_NAMED_FUNC_EXPR, /**< push named function expression */ + VM_OC_SET_PROPERTY, /**< set property */ + + VM_OC_SET_GETTER, /**< set getter */ + VM_OC_SET_SETTER, /**< set setter */ + VM_OC_PUSH_ARRAY, /**< push array */ + VM_OC_PUSH_ELISON, /**< push elison */ + VM_OC_APPEND_ARRAY, /**< append array */ + VM_OC_IDENT_REFERENCE, /**< ident reference */ + VM_OC_PROP_REFERENCE, /**< prop reference */ + VM_OC_PROP_GET, /**< prop get */ + + /* These eight opcodes must be in this order. */ + VM_OC_PROP_PRE_INCR, /**< prefix increment of a property */ + VM_OC_PROP_PRE_DECR, /**< prop prefix decrement of a property */ + VM_OC_PROP_POST_INCR, /**< prop postfix increment of a property */ + VM_OC_PROP_POST_DECR, /**< prop postfix decrement of a property */ + VM_OC_PRE_INCR, /**< prefix increment */ + VM_OC_PRE_DECR, /**< prefix decrement */ + VM_OC_POST_INCR, /**< postfix increment */ + VM_OC_POST_DECR, /**< postfix decrement */ + + VM_OC_PROP_DELETE, /**< delete property */ + VM_OC_DELETE, /**< delete */ + + VM_OC_MOV_IDENT, /**< move identifier register reference */ + VM_OC_ASSIGN, /**< assign */ + VM_OC_ASSIGN_PROP, /**< assign property */ + VM_OC_ASSIGN_PROP_THIS, /**< assign prop this */ + + VM_OC_RETURN, /**< return */ + VM_OC_RETURN_FUNCTION_END, /**< return at the end of a function/script */ + VM_OC_THROW, /**< throw */ + VM_OC_THROW_REFERENCE_ERROR, /**< throw reference error */ + + VM_OC_EVAL, /**< eval */ + VM_OC_CALL, /**< call */ + VM_OC_NEW, /**< new */ + VM_OC_RESOLVE_BASE_FOR_CALL, /**< resolve base value before call */ + VM_OC_ERROR, /**< error while the vm_loop is suspended */ + + VM_OC_JUMP, /**< jump */ + VM_OC_BRANCH_IF_NULLISH, /** branch if undefined or null */ + VM_OC_POP_REFERENCE, /** prop identifier or property reference from the stack */ + VM_OC_BRANCH_IF_STRICT_EQUAL, /**< branch if strict equal */ + + /* These four opcodes must be in this order. */ + VM_OC_BRANCH_IF_TRUE, /**< branch if true */ + VM_OC_BRANCH_IF_FALSE, /**< branch if false */ + VM_OC_BRANCH_IF_LOGICAL_TRUE, /**< branch if logical true */ + VM_OC_BRANCH_IF_LOGICAL_FALSE, /**< branch if logical false */ + + VM_OC_PLUS, /**< unary plus */ + VM_OC_MINUS, /**< unary minus */ + VM_OC_NOT, /**< not */ + VM_OC_BIT_NOT, /**< bitwise not */ + VM_OC_VOID, /**< void */ + VM_OC_TYPEOF_IDENT, /**< typeof identifier */ + VM_OC_TYPEOF, /**< typeof */ + + VM_OC_ADD, /**< binary add */ + VM_OC_SUB, /**< binary sub */ + VM_OC_MUL, /**< mul */ + VM_OC_DIV, /**< div */ + VM_OC_MOD, /**< mod */ + VM_OC_EXP, /**< exponentiation */ + + VM_OC_EQUAL, /**< equal */ + VM_OC_NOT_EQUAL, /**< not equal */ + VM_OC_STRICT_EQUAL, /**< strict equal */ + VM_OC_STRICT_NOT_EQUAL, /**< strict not equal */ + VM_OC_LESS, /**< less */ + VM_OC_GREATER, /**< greater */ + VM_OC_LESS_EQUAL, /**< less equal */ + VM_OC_GREATER_EQUAL, /**< greater equal */ + VM_OC_IN, /**< in */ + VM_OC_INSTANCEOF, /**< instanceof */ + + VM_OC_BIT_OR, /**< bitwise or */ + VM_OC_BIT_XOR, /**< bitwise xor */ + VM_OC_BIT_AND, /**< bitwise and */ + VM_OC_LEFT_SHIFT, /**< left shift */ + VM_OC_RIGHT_SHIFT, /**< right shift */ + VM_OC_UNS_RIGHT_SHIFT, /**< unsigned right shift */ + + VM_OC_BLOCK_CREATE_CONTEXT, /**< create lexical environment for blocks enclosed in braces */ + VM_OC_WITH, /**< with */ + VM_OC_FOR_IN_INIT, /**< for-in init context */ + VM_OC_FOR_IN_GET_NEXT, /**< get next */ + VM_OC_FOR_IN_HAS_NEXT, /**< has next */ + + VM_OC_TRY, /**< try */ + VM_OC_CATCH, /**< catch */ + VM_OC_FINALLY, /**< finally */ + VM_OC_CONTEXT_END, /**< context end */ + VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */ + + VM_OC_CREATE_BINDING, /**< create variables */ + VM_OC_CREATE_ARGUMENTS, /**< create arguments object */ + VM_OC_SET_BYTECODE_PTR, /**< setting bytecode pointer */ + VM_OC_VAR_EVAL, /**< variable and function evaluation */ + VM_OC_EXT_VAR_EVAL, /**< variable and function evaluation for + * functions with separate argument context */ + VM_OC_INIT_ARG_OR_FUNC, /**< create and init a function or argument binding */ + + VM_OC_CLASS_CALL_STATIC_BLOCK, /**< call the class static block */ + VM_OC_DEFINE_FIELD, /**< define class field */ + VM_OC_PRIVATE_PROP_REFERENCE, /**< reference to class private method */ + VM_OC_ASSIGN_PRIVATE, /**< assign to private field */ + VM_OC_PRIVATE_FIELD_ADD, /**< add private field */ + VM_OC_PRIVATE_PROP_GET, /**< get private field */ + VM_OC_PRIVATE_IN, /**< 'in' opcode handler for private identifiers */ + VM_OC_COLLECT_PRIVATE_PROPERTY, /**< collect private properties */ + VM_OC_CHECK_VAR, /**< check redeclared vars in the global scope */ + VM_OC_CHECK_LET, /**< check redeclared lets in the global scope */ + VM_OC_ASSIGN_LET_CONST, /**< assign values to let/const declarations */ + VM_OC_INIT_BINDING, /**< create and intialize a binding */ + VM_OC_THROW_CONST_ERROR, /**< throw invalid assignment to const variable error */ + VM_OC_COPY_TO_GLOBAL, /**< copy value to global lex env */ + VM_OC_COPY_FROM_ARG, /**< copy value from arg lex env */ + VM_OC_CLONE_CONTEXT, /**< clone lexical environment with let/const declarations */ + VM_OC_COPY_DATA_PROPERTIES, /**< copy data properties of an object */ + VM_OC_SET_COMPUTED_PROPERTY, /**< set computed property */ + + VM_OC_FOR_OF_INIT, /**< for-of init context */ + VM_OC_FOR_OF_GET_NEXT, /**< for-of get next */ + VM_OC_FOR_OF_HAS_NEXT, /**< for-of has next */ + VM_OC_FOR_AWAIT_OF_INIT, /**< for-await-of init context */ + VM_OC_FOR_AWAIT_OF_HAS_NEXT, /**< for-await-of has next */ + + VM_OC_LOCAL_EVAL, /**< eval in local context */ + VM_OC_SUPER_CALL, /**< call the 'super' constructor */ + VM_OC_PUSH_CLASS_ENVIRONMENT, /**< push class environment */ + VM_OC_PUSH_IMPLICIT_CTOR, /**< create implicit class constructor */ + VM_OC_INIT_CLASS, /**< initialize class */ + VM_OC_FINALIZE_CLASS, /**< finalize class */ + VM_OC_SET_FIELD_INIT, /**< store the class field initializer function */ + VM_OC_SET_STATIC_FIELD_INIT, /**< store the static class field initializer function */ + VM_OC_RUN_FIELD_INIT, /**< run the class field initializer function */ + VM_OC_RUN_STATIC_FIELD_INIT, /**< run the static class field initializer function */ + VM_OC_SET_NEXT_COMPUTED_FIELD, /**< set the next computed field of a class */ + VM_OC_PUSH_SUPER_CONSTRUCTOR, /**< getSuperConstructor operation */ + VM_OC_RESOLVE_LEXICAL_THIS, /**< resolve this_binding from from the lexical environment */ + VM_OC_SUPER_REFERENCE, /**< push super reference */ + VM_OC_SET_HOME_OBJECT, /**< set the [[HomeObject]] environment in an object literal */ + VM_OC_OBJECT_LITERAL_HOME_ENV, /**< create/destroy [[HomeObject]] environment of an object literal */ + VM_OC_SET_FUNCTION_NAME, /**< set function name property */ + + VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */ + VM_OC_PUSH_REST_OBJECT, /**< push rest object */ + VM_OC_ITERATOR_CONTEXT_CREATE, /**< create iterator conext */ + VM_OC_ITERATOR_CONTEXT_END, /**< finalize iterator cotnext */ + VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */ + VM_OC_OBJ_INIT_CONTEXT_CREATE, /**< create object initializer context */ + VM_OC_OBJ_INIT_CONTEXT_END, /**< finalize object initializer context */ + VM_OC_OBJ_INIT_PUSH_REST, /**< push the object with the rest properties */ + VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */ + VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */ + VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */ + VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */ + VM_OC_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */ + VM_OC_CREATE_GENERATOR, /**< create a generator object */ + VM_OC_YIELD, /**< yield operation */ + VM_OC_ASYNC_YIELD, /**< async yield operation */ + VM_OC_ASYNC_YIELD_ITERATOR, /**< async yield iterator operation */ + VM_OC_AWAIT, /**< await operation */ + VM_OC_GENERATOR_AWAIT, /**< generator await operation */ + VM_OC_EXT_RETURN, /**< return which also clears the stack */ + VM_OC_ASYNC_EXIT, /**< return from async function */ + VM_OC_STRING_CONCAT, /**< string concatenation */ + VM_OC_GET_TEMPLATE_OBJECT, /**< GetTemplateObject operation */ + VM_OC_PUSH_NEW_TARGET, /**< push new.target onto the stack */ + VM_OC_REQUIRE_OBJECT_COERCIBLE, /**< RequireObjectCoercible opretaion */ + VM_OC_ASSIGN_SUPER, /**< assign super reference */ + VM_OC_SET__PROTO__, /**< set prototype when __proto__: form is used */ + VM_OC_PUSH_STATIC_FIELD_FUNC, /**< push static field initializer function */ + VM_OC_ADD_COMPUTED_FIELD, /**< add computed field name */ +#if JERRY_MODULE_SYSTEM + VM_OC_MODULE_IMPORT, /**< module dynamic import */ + VM_OC_MODULE_IMPORT_META, /**< module import.meta */ +#endif /* JERRY_MODULE_SYSTEM */ + + VM_OC_NONE, /**< a special opcode for unsupported byte codes */ +} vm_oc_types; + +/** + * Unused opcodes, but required by byte-code types. + */ +typedef enum +{ +#if !JERRY_MODULE_SYSTEM + VM_OC_MODULE_IMPORT = VM_OC_NONE, /**< module dynamic import */ + VM_OC_MODULE_IMPORT_META = VM_OC_NONE, /**< module import.meta */ +#endif /* JERRY_MODULE_SYSTEM */ + + VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */ +} vm_oc_unused_types; + +/** + * Decrement operator. + */ +#define VM_OC_DECREMENT_OPERATOR_FLAG 0x1 + +/** + * Postfix increment/decrement operator. + */ +#define VM_OC_POST_INCR_DECR_OPERATOR_FLAG 0x2 + +/** + * An named variable is updated by the increment/decrement operator. + */ +#define VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG 0x4 + +/** + * Jump to target offset if input value is logical false. + */ +#define VM_OC_BRANCH_IF_FALSE_FLAG 0x1 + +/** + * Branch optimized for logical and/or opcodes. + */ +#define VM_OC_LOGICAL_BRANCH_FLAG 0x2 + +/** + * Bit index shift for non-static property initializers. + */ +#define VM_OC_NON_STATIC_SHIFT 15 + +/** + * This flag is set for static property initializers. + */ +#define VM_OC_NON_STATIC_FLAG (0x1 << VM_OC_NON_STATIC_SHIFT) + +/** + * Position of "put result" opcode. + */ +#define VM_OC_PUT_RESULT_SHIFT 11 + +/** + * Mask of "put result" opcode. + */ +#define VM_OC_PUT_RESULT_MASK 0xf + +/** + * Generate a "put result" opcode flag bit. + */ +#define VM_OC_PUT_RESULT_CREATE_FLAG(V) (((V) &VM_OC_PUT_RESULT_MASK) << VM_OC_PUT_RESULT_SHIFT) + +/** + * Checks whether the result is stored somewhere. + */ +#define VM_OC_HAS_PUT_RESULT(V) ((V) & (VM_OC_PUT_RESULT_MASK << VM_OC_PUT_RESULT_SHIFT)) + +/** + * Specify where the result is stored + */ +typedef enum +{ + VM_OC_PUT_IDENT = VM_OC_PUT_RESULT_CREATE_FLAG (0x1), + VM_OC_PUT_REFERENCE = VM_OC_PUT_RESULT_CREATE_FLAG (0x2), + VM_OC_PUT_STACK = VM_OC_PUT_RESULT_CREATE_FLAG (0x4), + VM_OC_PUT_BLOCK = VM_OC_PUT_RESULT_CREATE_FLAG (0x8), +} vm_oc_put_types; + +/** + * Non-recursive vm_loop: the vm_loop can be suspended + * to execute a call /construct operation. These return + * types of the vm_loop tells whether a call operation + * is in progress or the vm_loop is finished. + */ +typedef enum +{ + VM_NO_EXEC_OP, /**< do nothing */ + VM_EXEC_CALL, /**< invoke a function */ + VM_EXEC_SUPER_CALL, /**< invoke a function through 'super' keyword */ + VM_EXEC_SPREAD_OP, /**< call/construct operation with spreaded argument list */ + VM_EXEC_RETURN, /**< return with the completion value without freeing registers */ + VM_EXEC_CONSTRUCT, /**< construct a new object */ +} vm_call_operation; + +ecma_value_t vm_run_global (const ecma_compiled_code_t *bytecode_p, ecma_object_t *function_object_p); +ecma_value_t vm_run_eval (ecma_compiled_code_t *bytecode_data_p, uint32_t parse_opts); + +#if JERRY_MODULE_SYSTEM +ecma_value_t vm_run_module (ecma_module_t *module_p); +ecma_value_t vm_init_module_scope (ecma_module_t *module_p); +#endif /* JERRY_MODULE_SYSTEM */ + +ecma_value_t vm_run (vm_frame_ctx_shared_t *shared_p, ecma_value_t this_binding_value, ecma_object_t *lex_env_p); +ecma_value_t vm_execute (vm_frame_ctx_t *frame_ctx_p); + +bool vm_is_strict_mode (void); +bool vm_is_direct_eval_form_call (void); + +ecma_value_t vm_get_backtrace (uint32_t max_depth); + +/** + * @} + * @} + */ + +#endif /* !VM_H */ diff --git a/src/loaders/lottie/jerryscript/meson.build b/src/loaders/lottie/jerryscript/meson.build new file mode 100644 index 00000000..a8e063bb --- /dev/null +++ b/src/loaders/lottie/jerryscript/meson.build @@ -0,0 +1 @@ +subdir('jerry-core') diff --git a/src/loaders/lottie/meson.build b/src/loaders/lottie/meson.build index bd952a91..0042db5f 100644 --- a/src/loaders/lottie/meson.build +++ b/src/loaders/lottie/meson.build @@ -1,3 +1,7 @@ +if lottie_expressions + subdir('jerryscript') +endif + source_file = [ 'tvgLottieAnimation.cpp', 'tvgLottieBuilder.h',