Add restart command to the debugger (#2401)

With this feature the use can restart the actual debug session
(similar to the multiple source context reset) within a client.

JerryScript-DCO-1.0-Signed-off-by: Imre Kiss kissi.szeged@partner.samsung.com
This commit is contained in:
Imre Kiss 2018-06-22 05:18:18 +02:00 committed by yichoi
parent 35ac0e0445
commit e3265883fd
9 changed files with 205 additions and 94 deletions

View File

@ -30,7 +30,7 @@
*/
JERRY_STATIC_ASSERT (JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT == 27
&& JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT == 19
&& JERRY_DEBUGGER_VERSION == 3,
&& JERRY_DEBUGGER_VERSION == 4,
debugger_version_correlates_to_message_type_count);
/**

View File

@ -26,7 +26,7 @@
/**
* JerryScript debugger protocol version.
*/
#define JERRY_DEBUGGER_VERSION (3)
#define JERRY_DEBUGGER_VERSION (4)
/**
* Frequency of calling jerry_debugger_receive() by the VM.

View File

@ -28,7 +28,7 @@ import math
import time
# Expected debugger protocol version.
JERRY_DEBUGGER_VERSION = 3
JERRY_DEBUGGER_VERSION = 4
# Messages sent by the server to client.
JERRY_DEBUGGER_CONFIGURATION = 1
@ -513,6 +513,12 @@ class DebuggerPrompt(Cmd):
do_ms = do_memstats
def do_restart(self, _):
""" Restart the engine's debug session """
self._send_string(JERRY_DEBUGGER_EVAL_ABORT + "\"r353t\"", JERRY_DEBUGGER_EVAL)
do_res = do_restart
def store_client_sources(self, args):
self.client_sources = args

View File

@ -412,6 +412,25 @@ instance_alloc (size_t size,
#endif /* JERRY_ENABLE_EXTERNAL_CONTEXT */
/**
* Inits the engine and the debugger
*/
static void
init_engine (jerry_init_flag_t flags, /**< initialized flags for the engine */
bool debug_server, /**< enable the debugger init or not */
uint16_t debug_port) /**< the debugger port */
{
jerry_init (flags);
if (debug_server)
{
jerry_debugger_init (debug_port);
}
register_js_function ("assert", jerryx_handler_assert);
register_js_function ("gc", jerryx_handler_gc);
register_js_function ("print", jerryx_handler_print);
} /* init_engine */
int
main (int argc,
char **argv)
@ -591,15 +610,7 @@ main (int argc,
#endif /* JERRY_ENABLE_EXTERNAL_CONTEXT */
jerry_init (flags);
if (start_debug_server)
{
jerry_debugger_init (debug_port);
}
register_js_function ("assert", jerryx_handler_assert);
register_js_function ("gc", jerryx_handler_gc);
register_js_function ("print", jerryx_handler_print);
init_engine (flags, start_debug_server, debug_port);
jerry_value_t ret_value = jerry_create_undefined ();
@ -629,99 +640,139 @@ main (int argc,
}
}
if (!jerry_value_is_error (ret_value))
while (true)
{
for (int i = 0; i < files_counter; i++)
if (!jerry_value_is_error (ret_value))
{
size_t source_size;
const jerry_char_t *source_p = (jerry_char_t *) read_file (file_names[i], &source_size);
if (source_p == NULL)
for (int i = 0; i < files_counter; i++)
{
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Source file load error");
break;
}
size_t source_size;
const jerry_char_t *source_p = (jerry_char_t *) read_file (file_names[i], &source_size);
if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_size))
{
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ("Input must be a valid UTF-8 string."));
break;
}
ret_value = jerry_parse ((jerry_char_t *) file_names[i],
strlen (file_names[i]),
source_p,
source_size,
JERRY_PARSE_NO_OPTS);
if (!jerry_value_is_error (ret_value) && !is_parse_only)
{
jerry_value_t func_val = ret_value;
ret_value = jerry_run (func_val);
jerry_release_value (func_val);
}
if (jerry_value_is_error (ret_value))
{
break;
}
jerry_release_value (ret_value);
ret_value = jerry_create_undefined ();
}
}
if (is_wait_mode)
{
is_repl_mode = false;
if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER))
{
while (true)
{
jerry_debugger_wait_for_source_status_t receive_status;
do
if (source_p == NULL)
{
jerry_value_t run_result;
receive_status = jerry_debugger_wait_for_client_source (wait_for_source_callback,
NULL,
&run_result);
if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
{
ret_value = jerry_create_error (JERRY_ERROR_COMMON,
(jerry_char_t *) "Connection aborted before source arrived.");
}
if (receive_status == JERRY_DEBUGGER_SOURCE_END)
{
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "No more client source.\n");
}
jerry_release_value (run_result);
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Source file load error");
break;
}
while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
if (receive_status != JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED)
if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_size))
{
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ("Input must be a valid UTF-8 string."));
break;
}
ret_value = jerry_parse ((jerry_char_t *) file_names[i],
strlen (file_names[i]),
source_p,
source_size,
JERRY_PARSE_NO_OPTS);
if (!jerry_value_is_error (ret_value) && !is_parse_only)
{
jerry_value_t func_val = ret_value;
ret_value = jerry_run (func_val);
jerry_release_value (func_val);
}
if (jerry_value_is_error (ret_value))
{
break;
}
jerry_cleanup ();
jerry_init (flags);
jerry_debugger_init (debug_port);
register_js_function ("assert", jerryx_handler_assert);
register_js_function ("gc", jerryx_handler_gc);
register_js_function ("print", jerryx_handler_print);
jerry_release_value (ret_value);
ret_value = jerry_create_undefined ();
}
}
if (is_wait_mode)
{
is_repl_mode = false;
if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER))
{
while (true)
{
jerry_debugger_wait_for_source_status_t receive_status;
do
{
jerry_value_t run_result;
receive_status = jerry_debugger_wait_for_client_source (wait_for_source_callback,
NULL,
&run_result);
if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
{
ret_value = jerry_create_error (JERRY_ERROR_COMMON,
(jerry_char_t *) "Connection aborted before source arrived.");
}
if (receive_status == JERRY_DEBUGGER_SOURCE_END)
{
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "No more client source.\n");
}
if (jerry_value_is_abort (run_result))
{
ret_value = jerry_acquire_value (run_result);
}
jerry_release_value (run_result);
}
while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
if (receive_status != JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED)
{
break;
}
init_engine (flags, true, debug_port);
ret_value = jerry_create_undefined ();
}
}
}
bool restart = false;
if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER) && jerry_value_is_abort (ret_value))
{
jerry_value_t abort_value = jerry_get_value_from_error (ret_value, false);
if (jerry_value_is_string (abort_value))
{
jerry_char_t str_buf[5];
jerry_value_t str_val = jerry_value_to_string (abort_value);
jerry_size_t str_size = jerry_get_string_size (str_val);
if (str_size == 5)
{
jerry_string_to_char_buffer (str_val, str_buf, str_size);
if (memcmp ("r353t", (char *) (str_buf), 5) == 0)
{
jerry_release_value (ret_value);
restart = true;
}
}
jerry_release_value (str_val);
}
jerry_release_value (abort_value);
}
if (!restart)
{
break;
}
jerry_cleanup ();
init_engine (flags, true, debug_port);
ret_value = jerry_create_undefined ();
}
if (is_repl_mode)

View File

@ -4,9 +4,9 @@ Stopped at tests/debugger/do_help.js:15
Documented commands (type help <topic>):
========================================
abort bt display exception list next source
b c dump f memstats quit src
backtrace continue e finish ms s step
break delete eval help n scroll throw
abort bt display exception list next s step
b c dump f memstats quit scroll throw
backtrace continue e finish ms res source
break delete eval help n restart src
(jerry-debugger) quit

View File

@ -0,0 +1,4 @@
n
n
n
restart

View File

@ -0,0 +1,18 @@
Connecting to: localhost:5001
Stopped at tests/debugger/do_restart.js:23
(jerry-debugger) n
Stopped at tests/debugger/do_restart.js:24
(jerry-debugger) n
out: foo
Stopped at tests/debugger/do_restart.js:25
(jerry-debugger) n
out: bar
Stopped at tests/debugger/do_restart.js:24
(jerry-debugger) restart
Connecting to: localhost:5001
Stopped at tests/debugger/do_restart.js:23
(jerry-debugger) continue
out: foo
out: bar
out: foo
out: bar

View File

@ -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.
function foo() {
print("foo");
}
function bar() {
print("bar");
}
for (var i = 0; i < 2; i++) {
foo();
bar();
}

View File

@ -37,6 +37,12 @@ sleep 1s
RESULT_TEMP=`mktemp ${TEST_CASE}.out.XXXXXXXXXX`
(cat "${TEST_CASE}.cmd" | ${DEBUGGER_CLIENT} --non-interactive ${CLIENT_ARGS}) &> ${RESULT_TEMP}
if [[ $TEST_CASE == *"restart"* ]]; then
CONTINUE_CASE=$(sed "s/restart/continue/g" <<< "$TEST_CASE")
(cat "${CONTINUE_CASE}.cmd" | ${DEBUGGER_CLIENT} --non-interactive ${CLIENT_ARGS}) &>> ${RESULT_TEMP}
fi
diff -U0 ${TEST_CASE}.expected ${RESULT_TEMP}
STATUS_CODE=$?