mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
260 lines
7.9 KiB
C
260 lines
7.9 KiB
C
/* Copyright JS Foundation and other contributors, http://js.foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS
|
|
* WITHOUT 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 jerry_value_t
|
|
backtrace_handler (const jerry_value_t function_obj, /**< function object */
|
|
const jerry_value_t this_val, /**< this value */
|
|
const jerry_value_t args_p[], /**< argument list */
|
|
const jerry_length_t args_count) /**< argument count */
|
|
{
|
|
JERRY_UNUSED (function_obj);
|
|
JERRY_UNUSED (this_val);
|
|
|
|
uint32_t max_depth = 0;
|
|
|
|
if (args_count > 0 && jerry_value_is_number (args_p[0]))
|
|
{
|
|
max_depth = (uint32_t) jerry_get_number_value (args_p[0]);
|
|
}
|
|
|
|
return jerry_get_backtrace (max_depth);
|
|
} /* backtrace_handler */
|
|
|
|
static jerry_value_t
|
|
run (const char *resource_name_p, /**< resource name */
|
|
const char *source_p) /**< source code */
|
|
{
|
|
jerry_value_t code = jerry_parse ((const jerry_char_t *) resource_name_p,
|
|
strlen (resource_name_p),
|
|
(const jerry_char_t *) source_p,
|
|
strlen (source_p),
|
|
JERRY_PARSE_NO_OPTS);
|
|
TEST_ASSERT (!jerry_value_is_error (code));
|
|
|
|
jerry_value_t result = jerry_run (code);
|
|
jerry_release_value (code);
|
|
|
|
return result;
|
|
} /* run */
|
|
|
|
static void
|
|
compare (jerry_value_t array, /**< array */
|
|
uint32_t index, /**< item index */
|
|
const char *str) /**< string to compare */
|
|
{
|
|
jerry_char_t buf[64];
|
|
|
|
size_t len = strlen (str);
|
|
|
|
TEST_ASSERT (len < sizeof (buf));
|
|
|
|
jerry_value_t value = jerry_get_property_by_index (array, index);
|
|
|
|
TEST_ASSERT (!jerry_value_is_error (value)
|
|
&& jerry_value_is_string (value));
|
|
|
|
TEST_ASSERT (jerry_get_string_size (value) == len);
|
|
|
|
jerry_size_t str_len = jerry_string_to_char_buffer (value, buf, (jerry_size_t) len);
|
|
TEST_ASSERT (str_len == len);
|
|
|
|
jerry_release_value (value);
|
|
|
|
TEST_ASSERT (memcmp (buf, str, len) == 0);
|
|
} /* compare */
|
|
|
|
static void
|
|
test_get_backtrace_api_call (void)
|
|
{
|
|
jerry_init (JERRY_INIT_EMPTY);
|
|
|
|
jerry_value_t global = jerry_get_global_object ();
|
|
|
|
jerry_value_t func = jerry_create_external_function (backtrace_handler);
|
|
jerry_value_t name = jerry_create_string ((const jerry_char_t *) "backtrace");
|
|
jerry_value_t result = jerry_set_property (global, name, func);
|
|
TEST_ASSERT (!jerry_value_is_error (result));
|
|
|
|
jerry_release_value (result);
|
|
jerry_release_value (name);
|
|
jerry_release_value (func);
|
|
|
|
jerry_release_value (global);
|
|
|
|
const char *source = ("function f() {\n"
|
|
" return backtrace(0);\n"
|
|
"}\n"
|
|
"\n"
|
|
"function g() {\n"
|
|
" return f();\n"
|
|
"}\n"
|
|
"\n"
|
|
"function h() {\n"
|
|
" return g();\n"
|
|
"}\n"
|
|
"\n"
|
|
"h();\n");
|
|
|
|
jerry_value_t backtrace = run ("something.js", source);
|
|
|
|
TEST_ASSERT (!jerry_value_is_error (backtrace)
|
|
&& jerry_value_is_array (backtrace));
|
|
|
|
TEST_ASSERT (jerry_get_array_length (backtrace) == 4);
|
|
|
|
compare (backtrace, 0, "something.js:2");
|
|
compare (backtrace, 1, "something.js:6");
|
|
compare (backtrace, 2, "something.js:10");
|
|
compare (backtrace, 3, "something.js:13");
|
|
|
|
jerry_release_value (backtrace);
|
|
|
|
/* Depth set to 2 this time. */
|
|
|
|
source = ("function f() {\n"
|
|
" return backtrace(2);\n"
|
|
"}\n"
|
|
"\n"
|
|
"function g() {\n"
|
|
" return f();\n"
|
|
"}\n"
|
|
"\n"
|
|
"function h() {\n"
|
|
" return g();\n"
|
|
"}\n"
|
|
"\n"
|
|
"h();\n");
|
|
|
|
backtrace = run ("something_else.js", source);
|
|
|
|
TEST_ASSERT (!jerry_value_is_error (backtrace)
|
|
&& jerry_value_is_array (backtrace));
|
|
|
|
TEST_ASSERT (jerry_get_array_length (backtrace) == 2);
|
|
|
|
compare (backtrace, 0, "something_else.js:2");
|
|
compare (backtrace, 1, "something_else.js:6");
|
|
|
|
jerry_release_value (backtrace);
|
|
|
|
jerry_cleanup ();
|
|
} /* test_get_backtrace_api_call */
|
|
|
|
static void
|
|
test_exception_backtrace (void)
|
|
{
|
|
jerry_init (JERRY_INIT_EMPTY);
|
|
|
|
const char *source = ("function f() {\n"
|
|
" undef_reference;\n"
|
|
"}\n"
|
|
"\n"
|
|
"function g() {\n"
|
|
" return f();\n"
|
|
"}\n"
|
|
"\n"
|
|
"g();\n");
|
|
|
|
jerry_value_t error = run ("bad.js", source);
|
|
|
|
TEST_ASSERT (jerry_value_is_error (error));
|
|
|
|
error = jerry_get_value_from_error (error, true);
|
|
|
|
TEST_ASSERT (jerry_value_is_object (error));
|
|
|
|
jerry_value_t name = jerry_create_string ((const jerry_char_t *) "stack");
|
|
jerry_value_t backtrace = jerry_get_property (error, name);
|
|
|
|
jerry_release_value (name);
|
|
jerry_release_value (error);
|
|
|
|
TEST_ASSERT (!jerry_value_is_error (backtrace)
|
|
&& jerry_value_is_array (backtrace));
|
|
|
|
TEST_ASSERT (jerry_get_array_length (backtrace) == 3);
|
|
|
|
compare (backtrace, 0, "bad.js:2");
|
|
compare (backtrace, 1, "bad.js:6");
|
|
compare (backtrace, 2, "bad.js:9");
|
|
|
|
jerry_release_value (backtrace);
|
|
|
|
jerry_cleanup ();
|
|
} /* test_exception_backtrace */
|
|
|
|
static void
|
|
test_large_line_count (void)
|
|
{
|
|
jerry_init (JERRY_INIT_EMPTY);
|
|
|
|
const char *source = ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
"g();\n");
|
|
|
|
jerry_value_t error = run ("bad.js", source);
|
|
|
|
TEST_ASSERT (jerry_value_is_error (error));
|
|
|
|
error = jerry_get_value_from_error (error, true);
|
|
|
|
TEST_ASSERT (jerry_value_is_object (error));
|
|
|
|
jerry_value_t name = jerry_create_string ((const jerry_char_t *) "stack");
|
|
jerry_value_t backtrace = jerry_get_property (error, name);
|
|
|
|
jerry_release_value (name);
|
|
jerry_release_value (error);
|
|
|
|
TEST_ASSERT (!jerry_value_is_error (backtrace)
|
|
&& jerry_value_is_array (backtrace));
|
|
|
|
TEST_ASSERT (jerry_get_array_length (backtrace) == 1);
|
|
|
|
compare (backtrace, 0, "bad.js:385");
|
|
|
|
jerry_release_value (backtrace);
|
|
|
|
jerry_cleanup ();
|
|
} /* test_large_line_count */
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
TEST_INIT ();
|
|
|
|
TEST_ASSERT (jerry_is_feature_enabled (JERRY_FEATURE_LINE_INFO));
|
|
|
|
test_get_backtrace_api_call ();
|
|
test_exception_backtrace ();
|
|
test_large_line_count ();
|
|
|
|
return 0;
|
|
} /* main */
|