From 2a82da62add363a33a5df5bc2f2295dd9a440b52 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Wed, 29 Sep 2021 12:34:38 +0200 Subject: [PATCH] Implement source info retrieval API function (#4780) JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- docs/02.API-REFERENCE.md | 143 ++++++++++++++++++- jerry-core/api/jerry.c | 184 ++++++++++++++++++++++++- jerry-core/include/jerryscript-core.h | 2 + jerry-core/include/jerryscript-types.h | 27 ++++ jerry-core/parser/js/js-lexer.c | 11 +- tests/unit-core/CMakeLists.txt | 1 + tests/unit-core/test-source-info.c | 162 ++++++++++++++++++++++ 7 files changed, 524 insertions(+), 6 deletions(-) create mode 100644 tests/unit-core/test-source-info.c diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index ed6278fbc..b3bb9fe9d 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -1413,6 +1413,49 @@ typedef struct - [jerry_exec_snapshot](#jerry_exec_snapshot) +## jerry_source_info_enabled_fields_t + +Enum which describes the enabled fields of [jerry_source_info_t](#jerry_source_info_t). +Possible values: + + - JERRY_SOURCE_INFO_HAS_SOURCE_CODE - source_code field is valid + - JERRY_SOURCE_INFO_HAS_FUNCTION_ARGUMENTS - function_arguments field is valid + - JERRY_SOURCE_INFO_HAS_SOURCE_RANGE - both source_range_start and source_range_length fields are valid + +*New in version [[NEXT_RELEASE]]*. + +**See also** + +- [jerry_source_info_t](#jerry_source_info_t) +- [jerry_get_source_info](#jerry_get_source_info) + +## jerry_source_info_t + +**Summary** + +Source related information of a script/module/function. + +**Prototype** + +```c +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; +``` + +*New in version [[NEXT_RELEASE]]*. + +**See also** + +- [jerry_source_info_enabled_fields_t](#jerry_source_info_enabled_fields_t) +- [jerry_get_source_info](#jerry_get_source_info) + + # General engine functions ## jerry_init @@ -11835,6 +11878,8 @@ jerry_get_user_value (const jerry_value_t value); **Example** +[doctest]: # () + ```c #include "jerryscript.h" @@ -11845,10 +11890,10 @@ main (void) const jerry_char_t script[] = "function abc() {} abc"; - jerry_value user_value = jerry_create_object (); + jerry_value_t user_value = jerry_create_object (); jerry_parse_options_t parse_options; - parse_options.options = ECMA_PARSE_HAS_USER_VALUE; + parse_options.options = JERRY_PARSE_HAS_USER_VALUE; parse_options.user_value = user_value; jerry_value_t parsed_code = jerry_parse (script, sizeof (script) - 1, &parse_options); @@ -11857,7 +11902,7 @@ main (void) /* The jerry_get_user_value returns the object which * was created by jerry_create_object before. */ - jerry_value user_value = jerry_get_user_value (parsed_code); + user_value = jerry_get_user_value (parsed_code); jerry_release_value (parsed_code); jerry_release_value (user_value); @@ -11872,6 +11917,98 @@ main (void) - [jerry_generate_snapshot](#jerry_generate_snapshot) - [jerry_exec_snapshot](#jerry_exec_snapshot) +## jerry_get_source_info + +**Summary** + +Returns a newly created source info structure corresponding to the passed script/module/function. +The function is lower level than `toString()` operation, but provides more contextual information. + +*Notes*: +- Returned value must be freed with [jerry_free_source_info](#jerry_free_source_info) when it +is no longer needed. +- This API depends on a build option (`JERRY_FUNCTION_TO_STRING`) and can be checked + in runtime with the `JERRY_FEATURE_FUNCTION_TO_STRING` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). + +**Prototype** + +```c +jerry_source_info_t *jerry_get_source_info (const jerry_value_t value); +``` +- `value` - script / module / function value which executes JavaScript + code (native modules / functions do not have source info). +- return + - source info - a newly created source info, if at least one field is available, + - NULL - otherwise + +*New in version [[NEXT_RELEASE]]*. + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + const jerry_char_t script[] = "function abc() {} abc"; + + jerry_value_t parsed_code = jerry_parse (script, sizeof (script) - 1, NULL); + + jerry_source_info_t *source_info_p = jerry_get_source_info (parsed_code); + jerry_release_value (parsed_code); + + if (source_info_p != NULL) + { + /* Check the information provided by jerry_get_source_info. */ + } + + jerry_free_source_info (source_info_p); + + jerry_cleanup (); + return 0; +} +``` + +**See also** + +- [jerry_free_source_info](#jerry_free_source_info) +- [jerry_source_info_t](#jerry_source_info_t) + +## jerry_free_source_info + +**Summary** + +Frees the the source info structure returned by [jerry_get_source_info](#jerry_get_source_info). + +*Notes*: +- This API depends on a build option (`JERRY_FUNCTION_TO_STRING`) and can be checked + in runtime with the `JERRY_FEATURE_FUNCTION_TO_STRING` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). + +**Prototype** + +```c +void jerry_free_source_info (jerry_source_info_t *source_info_p) +``` +- `source_info_p` - source info structure returned by [jerry_get_source_info](#jerry_get_source_info) + +*New in version [[NEXT_RELEASE]]*. + +**Example** + +See [jerry_get_source_info](#jerry_get_source_info) + +**See also** + +- [jerry_get_source_info](#jerry_get_source_info) +- [jerry_source_info_t](#jerry_source_info_t) + # Functions for realm objects diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index c127b1f47..821800b77 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -26,8 +26,9 @@ #include "ecma-comparison.h" #include "ecma-container-object.h" #include "ecma-dataview-object.h" -#include "ecma-exceptions.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-helpers.h" @@ -5513,6 +5514,187 @@ jerry_get_user_value (const jerry_value_t value) /**< jerry api value */ return ecma_copy_value (CBC_SCRIPT_GET_USER_VALUE (script_p)); } /* jerry_get_user_value */ +/** + * 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_get_source_info (const jerry_value_t value) /**< jerry api value */ +{ + jerry_assert_api_available (); + +#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 JERRY_ESNEXT + if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + ecma_extended_info_decode_vlq (&extended_info_p); + } +#endif /* JERRY_ESNEXT */ + + 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; + } +#if JERRY_ESNEXT + 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; + } +#endif /* JERRY_ESNEXT */ + 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_get_source_info */ + +/** + * Frees the the source info structure returned by jerry_get_source_info. + */ +void +jerry_free_source_info (jerry_source_info_t *source_info_p) /**< source info block */ +{ + jerry_assert_api_available (); + +#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_free_source_info */ + /** * Replaces the currently active realm with another realm. * diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index 39572343a..38e43f294 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -362,6 +362,8 @@ void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, voi void jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, void *user_p); jerry_value_t jerry_get_resource_name (const jerry_value_t value); jerry_value_t jerry_get_user_value (const jerry_value_t value); +jerry_source_info_t *jerry_get_source_info (const jerry_value_t value); +void jerry_free_source_info (jerry_source_info_t *source_info_p); /** * Array buffer components. diff --git a/jerry-core/include/jerryscript-types.h b/jerry-core/include/jerryscript-types.h index cbdef6dca..5416612e3 100644 --- a/jerry-core/include/jerryscript-types.h +++ b/jerry-core/include/jerryscript-types.h @@ -789,6 +789,33 @@ typedef enum JERRY_CONTAINER_OP_CLEAR, /**< Set/Map clear operation */ } jerry_container_operation_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; + /** * @} */ diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index c76de868e..e0c7220b3 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -3743,8 +3743,15 @@ lexer_init_line_info (parser_context_t *context_p) /**< context */ if (options_p != NULL && (options_p->options & JERRY_PARSE_HAS_START)) { - context_p->line = (options_p->start_line > 0) ? options_p->start_line : 1; - context_p->column = (options_p->start_column > 0) ? options_p->start_column : 1; + 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 */ diff --git a/tests/unit-core/CMakeLists.txt b/tests/unit-core/CMakeLists.txt index e782e8653..3bff72490 100644 --- a/tests/unit-core/CMakeLists.txt +++ b/tests/unit-core/CMakeLists.txt @@ -81,6 +81,7 @@ set(SOURCE_UNIT_TEST_MAIN_MODULES test-resource-name.c test-script-user-value.c test-snapshot.c + test-source-info.c test-special-proxy.c test-string-to-number.c test-stringbuilder.c diff --git a/tests/unit-core/test-source-info.c b/tests/unit-core/test-source-info.c new file mode 100644 index 000000000..2e578aa2c --- /dev/null +++ b/tests/unit-core/test-source-info.c @@ -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. + */ + +#include "config.h" +#include "jerryscript.h" + +#include "test-common.h" + +static void +compare_string (jerry_value_t left_string, /**< left string */ + const char *right_string_p) /**< right string */ +{ + size_t size = strlen (right_string_p); + uint8_t buffer[64]; + + TEST_ASSERT (size == jerry_get_string_size (left_string)); + TEST_ASSERT (size < sizeof (buffer)); + TEST_ASSERT (jerry_string_to_char_buffer (left_string, buffer, (jerry_size_t) size) == size); + TEST_ASSERT (memcmp (buffer, right_string_p, size) == 0); +} /* compare_string */ + +int +main (void) +{ + TEST_INIT (); + + jerry_init (JERRY_INIT_EMPTY); + + if (!jerry_is_feature_enabled (JERRY_FEATURE_FUNCTION_TO_STRING)) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Source code is not stored!\n"); + jerry_cleanup (); + return 0; + } + + jerry_value_t value = jerry_create_null (); + jerry_source_info_t *source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p == NULL); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + + value = jerry_create_object (); + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p == NULL); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + + jerry_parse_options_t parse_options; + const char *source_p = TEST_STRING_LITERAL ("var a = 6"); + + value = jerry_parse ((jerry_char_t *) source_p, strlen (source_p), NULL); + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p != NULL); + TEST_ASSERT (source_info_p->enabled_fields == JERRY_SOURCE_INFO_HAS_SOURCE_CODE); + compare_string (source_info_p->source_code, source_p); + TEST_ASSERT (jerry_value_is_undefined (source_info_p->function_arguments)); + TEST_ASSERT (source_info_p->source_range_start == 0); + TEST_ASSERT (source_info_p->source_range_length == 0); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + + if (jerry_is_feature_enabled (JERRY_FEATURE_MODULE)) + { + parse_options.options = JERRY_PARSE_MODULE; + + value = jerry_parse ((jerry_char_t *) source_p, strlen (source_p), &parse_options); + + jerry_value_t result = jerry_module_link (value, NULL, NULL); + TEST_ASSERT (!jerry_value_is_error (result)); + jerry_release_value (result); + + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p != NULL); + TEST_ASSERT (source_info_p->enabled_fields == JERRY_SOURCE_INFO_HAS_SOURCE_CODE); + compare_string (source_info_p->source_code, source_p); + TEST_ASSERT (jerry_value_is_undefined (source_info_p->function_arguments)); + TEST_ASSERT (source_info_p->source_range_start == 0); + TEST_ASSERT (source_info_p->source_range_length == 0); + jerry_free_source_info (source_info_p); + + result = jerry_module_evaluate (value); + TEST_ASSERT (!jerry_value_is_error (result)); + jerry_release_value (result); + + /* Byte code is released after a successful evaluation. */ + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p == NULL); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + } + + source_p = TEST_STRING_LITERAL ("( function f() {} )"); + + value = jerry_eval ((const jerry_char_t *) source_p, strlen (source_p), 0); + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p != NULL); + TEST_ASSERT (source_info_p->enabled_fields == (JERRY_SOURCE_INFO_HAS_SOURCE_CODE + | JERRY_SOURCE_INFO_HAS_SOURCE_RANGE)); + compare_string (source_info_p->source_code, source_p); + TEST_ASSERT (jerry_value_is_undefined (source_info_p->function_arguments)); + TEST_ASSERT (source_info_p->source_range_start == 2); + TEST_ASSERT (source_info_p->source_range_length == 15); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + + source_p = TEST_STRING_LITERAL ("new Function('a', 'b', 'return 0;')"); + + value = jerry_eval ((const jerry_char_t *) source_p, strlen (source_p), 0); + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p != NULL); + TEST_ASSERT (source_info_p->enabled_fields == (JERRY_SOURCE_INFO_HAS_SOURCE_CODE + | JERRY_SOURCE_INFO_HAS_FUNCTION_ARGUMENTS)); + compare_string (source_info_p->source_code, "return 0;"); + compare_string (source_info_p->function_arguments, "a,b"); + TEST_ASSERT (source_info_p->source_range_start == 0); + TEST_ASSERT (source_info_p->source_range_length == 0); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + + source_p = TEST_STRING_LITERAL ("(new Function('a = ( function() { } )', 'return a;'))()"); + + value = jerry_eval ((const jerry_char_t *) source_p, strlen (source_p), 0); + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p != NULL); + TEST_ASSERT (source_info_p->enabled_fields == (JERRY_SOURCE_INFO_HAS_SOURCE_CODE + | JERRY_SOURCE_INFO_HAS_SOURCE_RANGE)); + compare_string (source_info_p->source_code, "a = ( function() { } )"); + TEST_ASSERT (jerry_value_is_undefined (source_info_p->function_arguments)); + TEST_ASSERT (source_info_p->source_range_start == 6); + TEST_ASSERT (source_info_p->source_range_length == 14); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + + source_p = TEST_STRING_LITERAL ("(function f(a) { return 7 }).bind({})"); + + value = jerry_eval ((const jerry_char_t *) source_p, strlen (source_p), 0); + source_info_p = jerry_get_source_info (value); + TEST_ASSERT (source_info_p != NULL); + TEST_ASSERT (source_info_p->enabled_fields == (JERRY_SOURCE_INFO_HAS_SOURCE_CODE + | JERRY_SOURCE_INFO_HAS_SOURCE_RANGE)); + compare_string (source_info_p->source_code, source_p); + TEST_ASSERT (jerry_value_is_undefined (source_info_p->function_arguments)); + TEST_ASSERT (source_info_p->source_range_start == 1); + TEST_ASSERT (source_info_p->source_range_length == 26); + jerry_free_source_info (source_info_p); + jerry_release_value (value); + + jerry_cleanup (); + return 0; +} /* main */