Introduce generic backtrace capturing (#4555)
Remove jerry_get_backtrace_from function JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -33,14 +33,109 @@ backtrace_handler (const jerry_value_t function_obj, /**< function object */
|
||||
max_depth = (uint32_t) jerry_get_number_value (args_p[0]);
|
||||
}
|
||||
|
||||
if (args_count >= 2)
|
||||
{
|
||||
return jerry_get_backtrace_from (max_depth, args_p[1]);
|
||||
}
|
||||
|
||||
return jerry_get_backtrace (max_depth);
|
||||
} /* backtrace_handler */
|
||||
|
||||
static void
|
||||
compare_string (jerry_value_t left_value, /* string value */
|
||||
const char *right_p) /* string to compare */
|
||||
{
|
||||
jerry_char_t buffer[64];
|
||||
size_t length = strlen (right_p);
|
||||
|
||||
TEST_ASSERT (length <= sizeof (buffer));
|
||||
TEST_ASSERT (jerry_value_is_string (left_value));
|
||||
TEST_ASSERT (jerry_get_string_size (left_value) == length);
|
||||
|
||||
TEST_ASSERT (jerry_string_to_char_buffer (left_value, buffer, sizeof (buffer)) == length);
|
||||
TEST_ASSERT (memcmp (buffer, right_p, length) == 0);
|
||||
} /* compare_string */
|
||||
|
||||
static const jerry_value_t *handler_args_p;
|
||||
static int frame_index;
|
||||
|
||||
static bool
|
||||
backtrace_callback (jerry_backtrace_frame_t *frame_p, /* frame information */
|
||||
void *user_p) /* user data */
|
||||
{
|
||||
TEST_ASSERT ((void *) handler_args_p == user_p);
|
||||
TEST_ASSERT (jerry_backtrace_get_frame_type (frame_p) == JERRY_BACKTRACE_FRAME_JS);
|
||||
|
||||
const jerry_backtrace_location_t *location_p = jerry_backtrace_get_location (frame_p);
|
||||
const jerry_value_t *function_p = jerry_backtrace_get_function (frame_p);
|
||||
|
||||
TEST_ASSERT (location_p != NULL);
|
||||
TEST_ASSERT (function_p != NULL);
|
||||
|
||||
compare_string (location_p->resource_name, "capture_test.js");
|
||||
|
||||
++frame_index;
|
||||
|
||||
if (frame_index == 1)
|
||||
{
|
||||
TEST_ASSERT (!jerry_backtrace_is_strict (frame_p));
|
||||
TEST_ASSERT (location_p->line == 2);
|
||||
TEST_ASSERT (location_p->column == 1);
|
||||
TEST_ASSERT (handler_args_p[0] == *function_p);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (frame_index == 2)
|
||||
{
|
||||
TEST_ASSERT (jerry_backtrace_is_strict (frame_p));
|
||||
TEST_ASSERT (location_p->line == 7);
|
||||
TEST_ASSERT (location_p->column == 1);
|
||||
TEST_ASSERT (handler_args_p[1] == *function_p);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_ASSERT (frame_index == 3);
|
||||
TEST_ASSERT (!jerry_backtrace_is_strict (frame_p));
|
||||
TEST_ASSERT (location_p->line == 11);
|
||||
TEST_ASSERT (location_p->column == 1);
|
||||
TEST_ASSERT (handler_args_p[2] == *function_p);
|
||||
return false;
|
||||
} /* backtrace_callback */
|
||||
|
||||
static jerry_value_t
|
||||
capture_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);
|
||||
JERRY_UNUSED (args_p);
|
||||
JERRY_UNUSED (args_count);
|
||||
|
||||
TEST_ASSERT (args_count == 3);
|
||||
|
||||
frame_index = 0;
|
||||
handler_args_p = args_p;
|
||||
jerry_backtrace_capture (backtrace_callback, (void *) args_p);
|
||||
TEST_ASSERT (frame_index == 3);
|
||||
|
||||
return jerry_create_undefined ();
|
||||
} /* capture_handler */
|
||||
|
||||
static void
|
||||
register_callback (jerry_external_handler_t handler_p, /**< callback function */
|
||||
char *name_p) /**< name of the function */
|
||||
{
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
jerry_value_t func = jerry_create_external_function (handler_p);
|
||||
jerry_value_t name = jerry_create_string ((const jerry_char_t *) name_p);
|
||||
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);
|
||||
} /* register_callback */
|
||||
|
||||
static jerry_value_t
|
||||
run (const char *resource_name_p, /**< resource name */
|
||||
const char *source_p) /**< source code */
|
||||
@@ -89,18 +184,8 @@ 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);
|
||||
register_callback (backtrace_handler, "backtrace");
|
||||
register_callback (capture_handler, "capture");
|
||||
|
||||
const char *source = ("function f() {\n"
|
||||
" return backtrace(0);\n"
|
||||
@@ -158,13 +243,14 @@ test_get_backtrace_api_call (void)
|
||||
|
||||
jerry_release_value (backtrace);
|
||||
|
||||
/* Ignore f and g this time. */
|
||||
/* Test frame capturing. */
|
||||
|
||||
source = ("function f() {\n"
|
||||
" return backtrace(0, g);\n"
|
||||
" return capture(f, g, h);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g() {\n"
|
||||
" 'use strict';\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
@@ -174,77 +260,9 @@ test_get_backtrace_api_call (void)
|
||||
"\n"
|
||||
"h();\n");
|
||||
|
||||
backtrace = run ("something_ignore.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_ignore.js:10");
|
||||
compare (backtrace, 1, "something_ignore.js:13");
|
||||
|
||||
jerry_release_value (backtrace);
|
||||
|
||||
/* Use bound function this time. */
|
||||
|
||||
source = ("function f() {\n"
|
||||
" return backtrace(0, i);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function g(u, v) {\n"
|
||||
" return v();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"var h = g.bind(null, 0)\n"
|
||||
"var i = h.bind(null, f)\n"
|
||||
"\n"
|
||||
"function j() {\n"
|
||||
" return i();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"j();\n");
|
||||
|
||||
backtrace = run ("something_bound.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_bound.js:13");
|
||||
compare (backtrace, 1, "something_bound.js:16");
|
||||
|
||||
jerry_release_value (backtrace);
|
||||
|
||||
/* Use invalid function this time. */
|
||||
|
||||
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");
|
||||
|
||||
backtrace = run ("nothing_ignore.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, "nothing_ignore.js:2");
|
||||
compare (backtrace, 1, "nothing_ignore.js:6");
|
||||
compare (backtrace, 2, "nothing_ignore.js:10");
|
||||
compare (backtrace, 3, "nothing_ignore.js:13");
|
||||
backtrace = run ("capture_test.js", source);
|
||||
|
||||
TEST_ASSERT (jerry_value_is_undefined (backtrace));
|
||||
jerry_release_value (backtrace);
|
||||
|
||||
jerry_cleanup ();
|
||||
|
||||
Reference in New Issue
Block a user